0x01:正则表达式是啥子嘛
正则表达式(简称 Regex)是一些字符和特殊符号组成的字符串,它们描述了模式的重复或者表述多个字符。正则表达式可以按照某种模式匹配一系列有相似特征的字符串。
在Python 术语中,主要有两种方式完成模式匹配: “搜索”(search),即在字符串的任意部分中搜索匹配的模式;而 “匹配” (matching)是指 判断一个字符串能否从起始处或者部分地匹配的模式。 搜索通过 search()函数或方法来实现,而匹配通过调用 match() 函数或方法来实现。
0x02:常见的正则表达式符号和特殊字符
表示法 |
描述 |
正则表达式示例 |
符号 |
|
|
re1 | re2 |
匹配正则表达式 re1或者re2 |
foo | bar |
. |
匹配任何字符(除了\n 以外) |
b.b |
^ |
匹配字符串的起始部分 |
^Dear |
$ |
匹配字符串终止部分 |
/bin/*sh$ |
* |
匹配0次或者多次前面出现的正则表达式 |
[A-Za-Z0-9]* |
+ |
匹配1次或者多次前面出现的正则表达式 |
[a-z]+\.com |
? |
匹配0次或者1次前面出现的正则表达式 |
goo? |
{N} |
匹配N次前面出现的正则表达式 |
[0-9]{3} |
{M,M} |
匹配M~N次前面出现的正则表达式 |
[0-9]{5,9} |
[…] |
匹配来自字符集的任意单一字符 |
[aeiou] |
[…x-y…] |
匹配 x-y 范围中的任意单一字符 |
[0-9],[A-Za-z0-9] |
[^…] |
不匹配次字符集出现的任何一个字符,包括某一范围的字符(如果此字符集中出现) |
[^aeiou],[^A-Za-z0-9] |
(*|+|?|{})? |
用于匹配上面频繁出现\重复出现符号的非贪婪版本( *、+、?、{}) |
.*?[a-z] |
(…) |
匹配封闭的正则表达式,然后另存为子组 |
([0-9]{3})? , f(oo|u)bar |
表示法 |
描述 |
正则表达式示例 |
特殊字符 |
|
|
\d |
匹配任何十进制数字,于[0-9]一致(\D 与 \d相反,不匹配任何非数值型的数字) |
data\d+.txt |
\w |
匹配任何字母数字字符,与[A-Za-z0-9_]相同(\W与之相反) |
[A-Za-z_]\w+ |
\s |
匹配任何空格字符,与[\n\t\r\v\f]相同 (\S与之相反) |
of\sthe |
\b |
匹配任何单词边界(\B与之相反) |
\bthe\b |
\N |
匹配已保存的子组N(参见上面的(…)) |
price:\16 |
\c |
逐字匹配任何特殊字符c |
\. , \\ ,\* |
\A(\Z) |
匹配字符串的其实(结束) |
\ADear |
表示法 |
描述 |
正则表达式示例 |
扩展表示法 |
|
|
(?iLmsux) |
在正则表达式中嵌入一个或多个特殊“标记”参数(或者通过函数 \ 方法) |
(?x) ,(? im) |
(?:…) |
表示一个不用保存的分组 |
(?:\w+\.)* |
(?p…) |
像一个仅由name表述而不是数字ID表述的正则分组匹配 |
(?) |
(?p=name) |
在同一字符串中匹配由 (?p<name)分组的之前文本 |
(?=data) |
(?#…) |
表示注释,所有内容被忽略 |
(?#comment) |
(?=…) |
匹配条件是如果 … 出现之后的位置,而不使用输入字符串:称作正向前视断言 |
(?=.com) |
(?!…) |
匹配条件是如果 … 不出现之后的位置,而不使用输入字符串:称作负向前视断言 |
(?!.net) |
(?<=…) |
匹配条件是如果 … 出现之前的位置,而不使用输入字符串:称作正向后视断言 |
(?<=800-) |
(?<=…) |
匹配条件是如果 … 出现之前的位置,而不使用输入字符串:称作负向后视断言 |
(?<!192\.168\.) |
(?(id\name)Y|N) |
如果分组所提供的id或者 name 名称存在,就返回正则表达式的条件匹配Y,如果不存在,就返回N; |N 是可选项 |
(?(1)y|x) |
0x03:使用则一匹配符号匹配多个正则表达式模式
表示 则一匹配的管道符号 (|),表示从 一个 “ 从多个模式中选择其一”的操作。用于分割不同的正则表达式。
正则表达式模式 |
匹配的字符串 |
at | home |
at 、 home |
bat | bet | bit |
bat、bet、bit |
0x04:匹配任意单个字符
点号或者句点(.) 符号匹配除了换行符 \n 以外的任何字符。
正则表达式模式 |
匹配的字符串 |
f.o |
匹配在字母 f 和 o 之间的任意一个字符:例如 fao 、f9o、f#o等 |
.. |
任意两个字符 |
.end |
匹配在字符串end 之前的任意一个字符 |
0x05:从字符串的起始或者结尾或者单词边界匹配
正则表达式模式 |
匹配的字符串 |
^from |
任何以from作为起始的字符串 |
/bin/bash$ |
任何以/bin/bash作为结尾的字符串 |
^Subject:hi$ |
任何由单独的字符串Subject:hi构成的字符串 |
特殊字符 \b 和 \B 可以用来匹配字符边界。而两者的区别在于 \b 将用于匹配一个单词的 边界,这意味着如果一个模式必须位于单词的起始部分,就不管该单词前面(单词位于字符串中间)是否有特殊字符(单词位于行首)。\B 将匹配出现在一个单词中间的模式(即,不是单词边界)。
正则表达式模式 |
匹配的字符串 |
the |
任何包含the的字符串 |
\bthe |
任何以the 开始的字符串 |
\bthe\b |
进匹配单词 the |
\Bthe |
任何包含但并不以the作为起始的字符串 |
0x06: 创建字符集
如果某些时候,我们想匹配某些特定的字符,就可以使用方括号,该正则表达式能够匹配一对方括号中包含的任何字符。
正则表达式模式 |
匹配的字符串 |
b[aeiu]t |
bat、bet、bit、but |
[cr][23][op] |
一个包含三个字符的字符串,第一个字符是 c 或 r,然后是 2 或 3 ,后面是 o 或者 p。例如 c20、c3p、r2o、r3p |
0x07: 限定范围和否定
除了单字符以外,字符集还支持匹配指定的字符范围。方括号中两个符号中间用连字符 (-) 连接,用于指定一个字符的范围。如果脱字符 (^) 紧跟在左方括号后面,这个符号表示不匹配给定字符集中的 任何一个字符。
正则表达式模式 |
匹配的字符串 |
z.[0-9] |
字母 z 后面跟着任何一个字符,然后跟着一个数字 |
[r-u][env-y][us] |
字母 r 、s、t 或者 u 后面跟着 e、n、v、w、x、或者y ,然后跟 u 或者 s |
[^aeiou] |
一个非元音字符 |
[^\t\n] |
不匹配制表符 或者 \n |
[“-a] |
在一个ASCII系统中,所有字符位于 “ 和 a之间,即34-97之间 |
0x08:使用闭包操作符实现存在性和频数匹配
特殊符号 、+ 和 ? 所有 的这些都可以用于匹配一个、多个或者没有出现的字符串模式。星号或者星号操作符()将匹配其左边的正则表达式出现0此或者多次的情况(该操作叫做闭包)。 加号(+)操作符将匹配一次或者多次出现的正则表达式, 问号(?)操作符将匹配零次或者一次出现的正则表达式。
还有大括号操作符 {} , 里面或者单个值或者是由一对逗号分隔的值。这将匹配前面的正则表达式 N 次(如果是 {N} 或者一定范围的次数; 例如 {M,N} 匹配M -N 次出现,这些符号能够由 反斜线符号进行转义: *匹配星号,等等。
正则表达式模式 |
匹配的字符串 |
[dn]ot? |
字母 d 或者 n 后面跟一个 o,然后是最多一个t , 例如do、no、dot、not |
0?[1-9] |
任何数值数字,它可能前置一个0,例如,匹配一系列从 1-9 月的数值 |
[0-9]{15,16} |
匹配15或16个数字(例如信用卡号码) |
</?[^>]+> |
匹配全部有效的(和无效的)HTML标签 |
0x09:表示字符集的特殊字符
我们还可以使用 d 匹配任何十进制数字。另外一个 特殊字符 \w 能够表示全部字母数字的字符集,相当于[A-Za-z0-9]的缩写形式, \s 可以 用来表示空格字符。
正则表达式模式 |
匹配的字符串 |
\w+-\d+ |
一个由字母数字组成的字符串和一个连字符分隔的数字 |
[A-Za-z]\w* |
第一个字符是字母,其余字符(如果存在) 可以是数字或者字母 |
\w+@\w+\.com |
以 XXX@YYY.com格式表示简单的电子邮件地址 |
0x10: 使用圆括号指定分组
想要知道能否提取任何已经成功匹配的特定字符串或者子字符串, 可以使用一对 圆括号 包裹任何正则表达式。
当使用正则表达式时,一对圆括号可以实现一下任意一个(或者两个)功能:
正则表达式模式 |
匹配的字符串 |
\d+(\.\d*)? |
表示浮点数的字符串,例如 0.004 |
0x11: 扩展表示法
正则表达式模式 |
匹配的字符串 |
(?:\w+\.)* |
以 句点多为结尾的字符串,但是这些 匹配不会保存下来 |
(?=.com) |
如果一个字符串后面跟着 .com 才做匹配操作,并不使用任何目标字符串 |
(?!.net) |
如果一个字符串不后面跟着 .net 才做匹配操作 |
(?<=800-) |
如果一个字符串之前为 800- 才做匹配操作,假定为电话号码,同样,不适用任何输入字符串 |
(?<192\.168\.) |
如果一个字符串之前不是 192.168. 才做匹配 |
(?(1)x|y) |
如果匹配组(1)存在,就与 y 匹配,否则 ,就与 x 匹配 |