正则表达式
Python好用法¶
import re
pattern = re.compile(r'...')
# 方法1
## 注意:search() 仅返回第一个匹配到的。
result = pattern.search(text)
print(result.group()) # group()方法:返回正则匹配的指定分组(小括号),不指定或者 0 则表示返回匹配的整体。
# 方法2
## findall() 会匹配所有结果,放进列表。
results = pattern.findall(text)
print(results)
代码复杂时建议compile方法,简化代码,且不用多次编译pattern。不用compile的话如下:
注意¶
re.match
仅检查字符串开头是否匹配——所以可能有潜在漏洞。如果希望匹配整个字符串,可以在末尾加上"$"。
正则可视化¶
- 可视化: https://regexper.com/
- 测试: https://regex101.com/
- 解释/测试: https://regexr.com/
基础知识¶
常用元字符¶
元字符 | 说明 |
---|---|
. | 换行符以外的任意字符(包括. ) |
\w | 字母、数字、下划线、汉字。只考虑英文的话:等同于[a-z0-9A-Z_] 。 |
\s | 任意空白符。包括空格,制表符(Tab),换行符,中文全角空格等。 |
\d | 数字 |
\b | 单词的开始或结束 |
^ | 字符串开始 |
$ | 字符串结束 |
- 有些命令不支持。如Bash。参考: http://blog.chinaunix.net/uid-7665917-id-5766183.html
常用限定符¶
限定符 | 说明 |
---|---|
* | 重复0次或以上 |
+ | 重复1次或以上 |
? | 重复0次或1次 |
{n} | 重复n次 |
{n,} | 重复n次或以上 |
{n,m} | 重复n到m次 |
反义、否定/不匹配¶
- 大写字母为小写的非。如\S就是匹配非空白符。
- 方括号里的
^
表示不匹配。
语法 | 说明 |
---|---|
\W | \w的非 |
\S | \s的非 |
\D | \d的非 |
\B | \b的非 |
[\^X] | 不匹配X(匹配除了X以外的任意字符) |
[\^AIUEO] | 不匹配AIUEO |
[]
集合、区间——匹配方括号里任意一个¶
[aeiou]
就匹配任何一个英文元音字母
[.?!]
匹配标点符号(.或?或!)
|
逻辑或——用|把不同的规则分隔开¶
\d{5}-\d{4}|\d{5}
这个表达式用于匹配美国的邮政编码。美国邮编的规则是5位数字,或者用连字号间隔的9位数字。
之所以要给出这个例子是因为它能说明一个问题:使用分枝条件时,要注意各个条件的顺序。如果你把它改成\d{5}|\d{5}-\d{4}
的话,那么就只会匹配5位的邮编(以及9位邮编的前5位)。
原因是匹配分支条件时,将会从左到右地测试每个条件,如果满足了某个分支的话,就不会去再管其它的条件了。
()
分组——以便重复多次,或方便按分组序号提取¶
(\d{1,3}\.){3}\d{1,3}
是一个简单的IP地址匹配表达式
捕获¶
语法 | 说明 |
---|---|
(exp) | 匹配exp,并捕获文本到自动命名的分组里 |
(?\<name>exp) | 匹配exp,并捕获文本到命名为name的分组里。 也可以写成 (?'name'exp) 或(?P<name>exp) |
(?:exp) | 匹配exp,但是不捕获也不分组。 意义:不得不分组,但是之后并不想使用。 |
零宽断言¶
- 零宽:表示不匹配——指不匹配exp
- 与通配是不同的。如
*exp
,先行断言是输出*
,而通配是输出*exp
。
语法 | 说明 |
---|---|
(?=exp) | 匹配exp前面的位置。 也叫零宽度正预测先行断言(lookahead)。从最右端开始找,只获取前面的部分 |
(?<=exp) | 匹配exp后面的位置。 也叫零宽度正回顾后发断言(lookbehind)。从最左端开始找,只获取后面的部分 |
(?!exp) | 匹配后面不是exp的位置 |
(?<!exp) | 匹配前面不是exp的位置 |
注释¶
(?#comment)
:不对正则处理产生任何影响,仅注释效果。
懒惰&贪婪¶
语法 | 说明 |
---|---|
*? | 重复任意次,但尽可能少匹配 |
+? | 重复1次以上,但尽可能少匹配 |
?? | 重复0或1次,但尽可能少匹配 |
{n,m}? | 重复n到m次,但尽可能少匹配 |
{n,}? | 重复n次以上,但尽可能少匹配 |
a.*?b
匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab(第一到第三个字符)和ab(第四到第五个字符)——为什么第一个匹配是aab(第一到第三个字符)而不是ab(第二到第三个字符)?——简单地说,因为正则表达式有另一条规则,比懒惰/贪婪规则的优先级更高,即:最先开始的匹配拥有最高的优先权——The match that begins earliest wins。