正则表达式
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。