详解 Python3 正则表达式(一)
本文翻译自:https://docs.python.org/3.4/howto/regex.html
博主对此做了一些批注和修改 ^_^
正则表达式介绍
正则表达式(Regular expressions 也称为 REs,或 regexes 或 regex patterns)本质是一个微小的且高度专业化的编程语言。它被嵌入到 Python 中,并通过 re 模块提供给程序员使用。使用正则表达式,你需要指定一些规则来描述那些你希望匹配的字符串集合。这些字符串集合可能包含英语句子、e-mail 地址、TeX 命令,或任何你想要的东东。
正则表达式模式被编译成一系列的字节码,然后由一个 C 语言写的匹配引擎所执行。对于高级的使用,你可能需要关注匹配引擎是如何执行给定的 RE,并通过一定的方式来编写 RE,以便产生一个可以运行得更快的字节码。本文暂不讲解优化的细节,因为这需要你对匹配引擎的内部机制有一个很好的理解。但本文的例子均是符合标准的正则表达式语法。
批注:Python 的正则表达式引擎是用 C 语言写的,所以效率是极高的。另,所谓的正则表达式,这里说的 RE,就是上文我们提到的 “一些规则”。
正则表达式语言相对较小,并且受到限制,所以不是所有可能的字符处理任务都可以使用正则表达式来完成。还有一些特殊的任务,可以使用正则表达式来完成,但是表达式会因此而变得非常复杂。在这种情况下,你可能通过自已编写 Python 代码来处理会更好些;尽管 Python 代码比一个精巧的正则表达式执行起来会慢一些,但可能会更容易理解。
批注:这可能是大家常说的 “丑话说在前” 吧,大家别管它,正则表达式非常优秀,它可以处理你 98.3% 的文本任务,一定要好好学哦~~~~
简单的模式
我们将从最简单的正则表达式学习开始。由于正则表达式常用于操作字符串,因此我们从最常见的任务下手:字符匹配。
字符匹配
大多数字母和字符会匹配它们自身。举个例子,正则表达式 Fanfan 将完全匹配字符串 “Fanfan”(你可以启用不区分大小写模式,这将使得 Fanfan 可以匹配 “FANFAN” 或 “fanfan”,我们会在后边讨论这个话题)。
当然这个规则也有例外,有少数特殊的字符我们称之为元字符(metacharacter),它们并不能匹配自身,它们定义了字符类、子组匹配和模式重复次数等。本文用很大的篇幅专门讨论了各种元字符及其作用。
下边是元字符的完整列表(我们将在后边逐一讲解):
- . ^ $ * + ? {} [] \ | ()
批注:如果没有这些元字符,正则表达式就变得跟字符串的 find() 方法一样平庸了......
我们先来看下方括号 [ ],它们指定一个字符类用于存放你需要匹配的字符集合。可以单独列出需要匹配的字符,也可以通过两个字符和一个横杆 - 指定匹配的范围。例如 [abc] 会匹配字符 a,b 或 c;[a-c] 可以实现相同功能。后者使用范围来表示与前者相同的字符集合。如果你想只匹配小写字母,你的 RE 可能写成 [a-z]。
需要注意的一点是:元字符在方括号中不会触发 “特殊功能”,在字符类中,它们只匹配自身。例如 [akm$] 会匹配任何字符 'a','k','m' 或 '$',‘$’ 是一个元字符,但在方括号它不表示特殊含义,它只匹配 '$' 字符本身。
你还可以匹配方括号中未列出的所有其它字符,做法是在类的开头添加一个脱字符号 ^,例如 [^5] 会匹配除了 '5' 之外的任何字符。
或许最重要的元字符当属反斜杠 \ 了,跟 Python 的字符串规则一样,如果在反斜杠后边紧跟着一个元字符,那么元字符的 “特殊功能” 也不会被触发。例如你需要匹配符号 [ 或 \,你可以在它们前面加上一个反斜杠,以消除它们的特殊功能:\[,\\ 。
反斜杠后边跟一些字符还可以表示特殊的意义,例如表示十进制数字,表示所有的字母或者表示非空白的字符集合。
批注:反斜杠真牛逼,反斜杠后边跟元字符去除特殊功能,反斜杠后边跟着普通字符实现特殊功能。
让我们来举个例子:\w 匹配任何单词字符。如果正则表达式以字节的形式表示,这相当字符类 [a-zA-Z0-9_];如果正则表达式是一个字符串,\w 会匹配所有 Unicode 数据库(unicodedata 模块提供)中标记为字母的字符。你可以在编译正则表达式的时候,通过提供 re.ASCII 表示进一步限制 \w 的定义。
批注:re.ASCII 标志使得 \w 只能匹配 ASCII 字符,不要忘了,Python3 是 Unicode 的。
下边列举一些反斜杠加字符构成的特殊含义:
特殊字符 | 含义 |
\d | 匹配任何十进制数字,相当于类[0-9] |
\D | 与 \d 相反,匹配任何非十进制数字的字符,相当于 [^0-9] |
\s | 匹配任何空白字符(包含空格、换行符、制表符等),相当于类 [\t\n\r\f\v] |
\S | 与 \s 相反,匹配任何非空白字符,当相于类 [^\t\n\r\f\v] |
\w | 匹配任何单词字符,见上方解释 |
\W | 与 \w 相反 |
\b | 匹配单词的开始或结束 |
\B | 与 \b 相反 |
它们可以包含在一个字符类中,并且一样拥有特殊含义。例如 [\s,.] 是一个字符类,它将匹配任何空白字符(/s 的特殊含义),',' 或 ‘.’ 。
最后我们要讲的一个元字符是 .,它匹配除了换行符以外的任何字符。如果设置了 re.DOTALL 标志,. 将匹配包括换行在内的任何字符。
重复的事情
使用正则表达式能够轻松的匹配不同的字符集合,但 Python 字符串现有的方法却无法实现。然而,如果你认为这是正则表达式的唯一优势,那你就 too young too native 了。正则表达式有另一个强大的功能,就是你可以指定 RE 部分被重复的次数。
我们来看看 * 这个元字符,当然它不是匹配 '*' 字符本身(我们说过元字符都是有特殊能力的),它用于指定前一个字符匹配零次或者多次。
例如 ca*t 将匹配 ct(0 个字符 a),cat(1 个字符 a),caaat(3 个字符 a),等等。需要注意的是,由于受到 C 语言的 int 类型大小的内部限制,正则表达式引擎会限制字符 'a' 的重复个数不超过 20 亿个;不过,通常我们工作也用不到那么大的数据。
正则表达式默认的重复规则是贪婪的,当你重复匹配一个 RE 时,匹配引擎会尝试尽可能多的去匹配。直到 RE 不匹配或者到了结尾,匹配引擎就会回退一个字符,然后再继续尝试匹配。
我们通过例子一步步的给大家讲解什么叫 “贪婪”:先考虑一下表达式 a[bcd]*b,首先需要匹配字符 'a',然后零个到多个 [bcd],最后以 'b' 结尾。那现在想象一下,这个 RE 匹配字符串 abcbd 会怎样?
步骤 | 匹配 | 说明 |
1 | a | 匹配 RE 的第一个字符 'a' |
2 | abcbd | 引擎在符合规则的情况下尽可能地匹配 [bcd]*,直到该字符串的结尾 |
3 | 失败 | 引擎尝试匹配 RE 最后一个字符 ‘b’,但当前位置已经是字符串的结尾,所以失败告终 |
4 | abcb | 回退,所以 [bcd]* 匹配少一个字符 |
5 | 失败 | 再一次尝试匹配 RE 最后一个字符 'b',但字符串最后一个字符是 'd',所以失败告终 |
6 | abc | 再次回退,所以 [bcd]* 这次只匹配 'bc' |
7 | abcb | 再一次尝试匹配这符 'b',这一次字符串当前位置指向的字符正好是 'b',匹配成功 |
最终,RE 匹配的结果是 abcb 。
批注:正则表达式默认的匹配规则是贪婪的,后边有教你如何使用非贪婪的方法匹配。
另一个实现重复的元字符是 +,用于指定前一个字符匹配一次或者多次。
要特别注意 * 和 + 的区别:* 匹配的是零次或者多次,所以被重复的内容可能压根儿不会出现;+ 至少需要出现一次。例如 ca+t 会匹配 cat 和 caaat,但不会匹配 ct 。
还有两个表示重复的元字符,其中一个是问号 ?,用于指定前一个字符匹配零次或者一次。你可以这么想,它的作用就是把某种东西标志位可选的。
最灵活的应该是元字符 {m,n}(m 和 n 都是十进制数),上边讲到的几个元字符都可以使用它来表达,它的含义是前一个字符必须匹配 m 次到 n 次之间。例如 a/{1,3}b 会匹配 a/b,a//b 和 a///b 。但不会匹配 ab(没有斜杠);也不会匹配 a////b(斜杠超过三个)。
你可以省略 m 或者 n,这样的话,引擎会假定一个合理的值代替。省略 m,将被解释为下限 0;省略 n 则会被解释为无穷大(事实上是上边我们提到的 20 亿)。
批注:如果是 {,n} 相当于 {0,n};如果是 {m,} 相当于 {m,正无穷};如果是 {n},则是重复前一个字符 n 次。另外还有一个超容易出错的是写成 {m, n},看着挺美,但注意,正则表达式里边不能随意添加空格,不然会改变原来的含义。
最后,其实 * 、+ 和 ? 都可以使用 {m,n} 来代替。{0,} 跟 * 是一样的;{1,} 跟 + 是一样的;{0,1} 跟 ? 是一样的。不过还是鼓励大家记住并使用 * 、+ 和 ?,因为这些字符更短并且更容易阅读。
批注:还有一个原因是匹配引擎对 * + ? 做了优化,效率要更高些。
(本文完)
如果你喜欢这篇文章,请通过下方「评论」给我鼓励哦 ^_^
详解 Python3 正则表达式(一)的更多相关文章
- 详解 Python3 正则表达式(五)
上一篇:详解 Python3 正则表达式(四) 本文翻译自:https://docs.python.org/3.4/howto/regex.html 博主对此做了一些注明和修改 ^_^ 非捕获组和命名 ...
- 详解 Python3 正则表达式(四)
上一篇:详解 Python3 正则表达式(三) 本文翻译自:https://docs.python.org/3.4/howto/regex.html 博主对此做了一些注明和修改 ^_^ 更多强大的功能 ...
- 详解 Python3 正则表达式(三)
上一篇:详解 Python3 正则表达式(二) 本文翻译自:https://docs.python.org/3.4/howto/regex.html 博主对此做了一些批注和修改 ^_^ 模块级别的函数 ...
- 详解 Python3 正则表达式(二)
上一篇:详解 Python3 正则表达式(一) 本文翻译自:https://docs.python.org/3.4/howto/regex.html 博主对此做了一些批注和修改 ^_^ 使用正则表达式 ...
- Java 正则表达式详解_正则表达式
body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...
- (转)详解Python3 中hasattr()、getattr()、setattr()、delattr()函数及示例代码数
原文:https://www.jb51.net/article/138363.htm hasattr()函数 hasattr()函数用于判断是否包含对应的属性 语法: hasattr(object,n ...
- 详解JMeter正则表达式
详解JMeter正则表达式(1) 1.概览 JMeter中包含范本匹配软件Apache Jakarta ORO .在Jakarta网站上有一些关于它的文档,例如a summary of the pat ...
- 【转】详解Java正则表达式语法
(转自: http://www.jb51.net/article/76354.htm) 这篇文章主要介绍了Java正则表达式语法,包括常用正则表达式.匹配验证-验证Email是否正确以及字符串中查询字 ...
- 转:详解JMeter正则表达式(2)
例如, 引用名称:MYREF. 正则表达式:name="(.+?)" value="(.+?)". 模板:$1$$2$. 不要用/ /封装正则表达式. 如下变量 ...
随机推荐
- mybatis支持的jdbc类型
参考mybatis的枚举JdbcType源码: 关于这些类型mybatis是如何处理可以看一下TypeHandler类的源码.
- WCF传输协议
典型传输协议下的(1)HTTP和HTTPSHTTPS(安全超文本传输协议).它是为了在WWW上解决安全的数据传输而设计的.HTTS是采用了SSL的HTTP,SSL是一种加密协议.它们默认的端口号分别是 ...
- Eclipse 无法编译,提示“错误: 找不到或无法加载主类”
jar包问题: 1.项目的Java Build Path中的Libraries中有个jar包的Source attachment指为了一个不可用的jar包, 解决办法是:将这个不可用的jar包remo ...
- ASPNET MVC Error 403.14
今天创建了一个新的ASPNET MVC 项目部署到本地, 生成成功后在浏览器中输入URL却发现报这个错 解决办法: 因为我的站点是4.5的,但是我没有设置Application Pool所以当前还是默 ...
- QT样式
最近在写QT的UI 分享一个助手网页 http://doc.qt.io/qt-4.8/stylesheet-examples.html
- 二阶SQL注入理解与体会
一:SQL注入分类 SQL注入一般分为两类:一阶SQL注入(普通SQL注入),二阶SQL注入 二:二者进行比较 0x01:一阶SQL注入: 1:一阶SQL注入发生在一个HTTP请求和响应中,对系统的攻 ...
- python实现读取类别频数数据画水平条形图
1.数据分组-->频数分布表 环境配置: import pandas as pd import numpy as np import matplotlib.pyplot as plt 按照你设定 ...
- 远程登录-出现身份验证错误[可能是由于CredSSP加密Oracle修正]
问题描述 远程桌面登录时,出现身份验证错误,要求的函数不正确,这可能是由于CredSSP加密Oracle修正. 原因,系统更新导致 CVE-2018-0886 的 CredSSP 更新 解决方法1 运 ...
- 关于Tomcat服务器接收到的请求参数乱码的问题
我们在编写的Controller 等服务器端的代码时,接受到的请求参数经常会乱码. 解决:在Tomcat 的安装目录下找到conf 文件夹下的server.xml文件用记事本打开. 找到 <Co ...
- git branch 进入编辑状态
命令行输入git branch,发现进入编辑状态,都要:wq,非常不方便,这样配置 git config --global core.pager ''