【Re】正则表达式
编辑常用字符及其含义
字符 | 描述 |
---|---|
. | 匹配除“\n”和"\r"之外的任何单个字符 |
\d | 匹配任何数字字符,和 [0-9] 相同 |
\D | 匹配任何非数字字符,和 [^0-9] 相同 |
\w | 匹配包含 a-zA-Z0-9 和下划线的字符串 |
\W | 匹配任何没有下划线和子母数字的字符串 |
\s | 匹配任何空白字符 |
\S | 匹配任何非空白字符 |
\b | 匹配是否到达了单词边界 |
\B | 匹配是否没有到达单词编辑 |
\ | 转义符 |
^ | 匹配输入字行首 |
$ | 匹配输入行尾 |
x|y | 匹配x或y |
[abc] | 字符集合,匹配任何包含小写字母 a、b、c 的字符串 |
[^abc] | 负值字符集合,匹配任何不包含小写字母 a、b、c 的字符串 |
[a-z] | 字符范围,匹配 a 到 z 范围内的任意小写字母字符 |
* | 匹配前面的子表达式任意次 |
+ | 匹配前面的子表达式一次或多次 |
? | 匹配前面的子表达式零次或一次 |
{n} | 匹配前面的子表达式确定的 n 次 |
{n,} | 匹配前面的子表达式至少匹配n次 |
{n,m} | 匹配前面的子表达式最少 n 次且最多 m 次 |
( ) | 将表达式定义为「组」(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 「\1」 到「\9」 的符号来引用 |
贪婪、非贪婪与侵占
贪婪:第一个匹配对象「往后尽可能多的」匹配,可以回退
非贪婪:第一个匹配对象「不往后尽可能多的」匹配
侵占:第一个匹配对象「往后尽可能多的」匹配,但不可以回退
匹配模式:
.*?(b.*b).*
匹配结果:booooooobbbb
匹配释义:左端的 b 非贪婪匹配,匹配到第一个符和的 b 便不再往后匹配,右端的 b 贪婪匹配,匹配至不能再匹配为止匹配模式:
.*(b.*?b).*
匹配结果:bb
匹配释义:左端的 b 贪婪匹配,匹配到不能再往后匹配为止,右端的 b 非贪婪匹配,匹配至第一个结束匹配模式:
.*?(b.*?b).*
匹配结果:booooooob
匹配释义:两端b非贪婪匹配,即匹配到第一个结束
贪婪非贪婪与最短匹配无关
案例:00000aba110aa000
贪婪:
a(.*)a
匹配结果:aba110aa非贪婪:
a(.*?)a
匹配结果:aba贪婪非贪婪,与是否在整个文本中想要匹配的对象是否最短无关
上述案例,最短结果应该是「aa」,仅用贪婪非贪婪是无法实现匹配结果最短的结果的。
贪婪与侵占的对比
贪婪模式
表达式中单独使用正则量词
? 、* 、+ 、{n,m}
的情况。特点:一次尽量多的匹配字符,但可以回退。
侵占模式
贪婪模式字符的后面添加一个 + 来表示的。
特点:一次尽量多的匹配字符,但不可以回退。
目标字符串:m232hjdhfd7474
贪婪正则:
\w+[a-z]
将上面的正则拆分成
\w+
和[a-z]
两个子表达式来看,\w+
称作 p1,[a-z]
称作 p2。
p1 属于贪婪模式,会一次性吃掉它所能吃掉的所有的字符,也就是子串 232hjdhfd7474;这样的话,就只剩下 $ 与 p2 进行匹配了,显然是匹配失败的。所以,第二轮尝试匹配时,p1 会吐出一个字符4,但此时 p2 还是得不到匹配。反复的这样吐出回退,直到吐出字符 d 时,d 能与 p2 完成匹配,这时正则表达式会返回一次成功匹配的结果,即字符串 232hjdhfd侵占正则:
\w++[a-z]
将上面的正则拆分成
\w++
和[a-z]
两个子表达式来看,\w++
称作 p1,[a-z]
称作 p2。
p1 属于侵占模式,它会一次性吃掉它所能够吃掉的所有字符,即子串 232hjdhfd7474,而且 p1 不会回退字符;这时,只剩下 $ 与 p2 进行匹配了,显然是匹配失败的,所以整个表达式匹配失败。
捕获与非捕获
捕获
(exp)
: 匹配 exp ,并捕获文本到自动命名的组里(「\1」)(?<name>exp)
:匹配 exp ,并捕获文本到名称为 name 的组里,也可以写成(?'name'exp)
非捕获
(?:exp1)exp2
:匹配到的 exp1 不放入到捕获组里面
import re
a = 'abcssdad123'
pattern1 = re.compile(r'(abc)(\w{4})')
pattern2 = re.compile(r'(?:abc)(\w{4})')
res1 = pattern1.search(a)
res2 = pattern2.search(a)
print(res1.groups())
print(res2.groups())
>> ('abc', 'ssda')
>> ('ssda',)
零宽断言
零宽断言都是属于非捕获的
表达式 | 描述 |
---|---|
| 正向肯定预查,仅当子表达式 X 在表达式 exp1 「右侧匹配」时才继续匹配 |
| 正向否定预查,仅当子表达式 X 在表达式 exp1 「右侧不匹配」时才继续匹配 |
| 反向肯定预查,仅当子表达式 X 在表达式 exp1「左侧匹配」时才继续匹配 |
| 反向否定预查,仅当子表达式 X 在表达式 exp1「左侧不匹配」时才继续匹配 |
[a-z](?=3)
匹配字母右侧「跟着」3 的字母
[a-z](?!3)
匹配字母右侧「不跟着」3 的字母
(?<=a)\d
匹配数字左侧的字符 「是」 a 的数字
(?<!=\a)\d+
匹配数字左侧的字符 「不是」 a 的数字
(?<!4)56(?=9)
查找56,要求左侧不能是4,右侧必须是9。5569的「56」匹配 ,4569中的「56」不匹配。
import re
a = 'a3 b4'
print(re.compile(r'[a-z](?=3)').findall(a))
print(re.compile(r'[a-z](?!3)').findall(a))
print(re.compile(r'(?<=a)\d').findall(a))
print(re.compile(r'(?<!a)\d').findall(a))
>> ['a']
>> ['b']
>> ['3']
>> ['4']
模式修正符
模式修正符 | 描述 |
---|---|
i | 匹配时不区分大小写 |
g | 全局匹配,查找所有的匹配项 |
m | 多行匹配,使边界字符「^」和「$」匹配每一行的开头和结尾 |
s | 特殊字符圆点,使「.」中包含换行符 「\n」,会将整段字符串视为单行,也称单行模式 |
x | 将表达式中的空白忽略 |
e | 弃用(配合函数preg_replace()使用, 可以把匹配来的字符串当作正则表达式执行) |
A | 强制从字符串开头匹配,相当于给表达式加了一个「^」 |
D | 强制以表达式结尾,相当于给表达式加了一个「$」 |
U | 正则表达式的特点是比较「贪婪」,使用该模式可以取消贪婪模式 |
- | 禁用 |
多个模式修正符可以一起用
(?i-s)
作用:不区分大小写,并禁用单行模式
模式修正符可以限定范围
表达式:
(?i)ab
(也可以写成(?i:)ab
)
作用:表示对(?i)
后的所有字符都开启不区分大小写的开关,故它可以匹配ab、aB、Ab、AB表达式:
(?i:a)b
表示只对a开启不区分大小写的开关,故它可以匹配ab和Ab,不能匹配aB和AB。
Python中的正则
match
:re.match(pattern, string[, flags])
从首字母开始开始匹配,string 如果包含 pattern 子串,则匹配成功,返回 Match 对象,失败则返回 None。若要 string 完全匹配 pattern,pattern 要以 $ 结尾。
search
:re.search(pattern, string[, flags])
若 string 中包含 pattern 子串,则返回 Match 对象,否则返回 None ,注意,如果 string 中存在多个 pattern 子串,只返回第一个。
findall
:re.findall(pattern, string[, flags])
返回string中所有与pattern相匹配的全部字串,返回形式为数组。
finditer
:re.finditer(pattern, string[, flags])
返回string中所有与pattern相匹配的全部字串,返回形式为迭代器。
match 对象
group()返回类型为字符串,表示返回整个匹配对象作为一个字符串
group(1)返回类型为字符串,表示返回正则表达式的第1个分组匹配的对象,group(0)等同于group()返回整个匹配对象
groups()返回类型为元祖,表示返回正则表达式每个分组匹配的对象依次放进元祖里,如果正则表达式没有(),则返回空元祖()。
参考文献
- 0
- 0
-
赞助
微信 -
分享