Python 的正则表达式

1 基本用法

1.1.1 匹配字符串的开头

1
^很

1.1.2 匹配字符串的末尾

1
蓝$

1.1.3 匹配除了换行符外的任意字符

指定 re.S(re.DOTALL) 时,可包括换行符

1
.

1.1.4 匹配方括号中任意一个字符

1
\[Pp\]`,`\[0-9\]

1.1.5: 匹配不在中括号中的字符

1
2
3
4
\[^...]

可匹配除了a,b,c之外的字符
[^abc]

1.1.6 : 匹配其前面的字符出现 0 次或多次,

1
2
可匹配 helll,he
hel*

1.1.7 匹配其前面的字符出现 1 次或多次,如

1
2
3
4
+

可匹配 helll,hel,但无法匹配he
hel+

1.1.8 匹配其前面的字符出现 0 次或 1 次,

1
2
3
4
?

可匹配hel,he,但无法匹配hell
hel?

1.1.9 匹配其前面的表达式出现 n 次,

1
2
3
4
{n}

可匹配food,但无法匹配pow
o{2}

1.1.10 匹配其前面的表达式出现 n 次以上,

1
2
3
4
{n,}

可匹配food,fooooood,无法匹配pow,`o{1,}`,等价于`o+`,`o{0,}`,`o*`
o{2,}

1.1.11 匹配其前面的表达式最少出现 n 次最多出现 m 次

1
2
3
4
{n,m}

可匹配food,foooood,无法匹配pow,fooooood,`o{0,1}`,等价于`o?`
o{2,5}

1.1.12 匹配 a 或 b

1
2
3
4
a|b

可匹配pack,pbck
p[a|b]ck

2 分组

2.1.1 对正则表达式分组,并返回括号中的内容

1
()

2.1.2 正则表达式包含三种可选标志:i, m, 或 x,只影响括号内的区域

1
(?imx)

2.1.3 正则表达式关闭 i, m, 或 x 可选标志,只影响括号内的区域

1
(?-imx)

2.1.4 类似 (), 但不表示一个组

1
(?: re)

2.1.5 在括号中使用 i, m, 或 x 可选标志

1
(?imx: re)

2.1.6 在括号中不使用 i, m, 或 x 可选标志

1
(?-imx: re) 

2.1.7 注释

1
\(?#...)

2.1.8 前向肯定界定符

1
2
3
4
5
6
(?=re): 

# 只抽取数字,且该数字后面跟的字符是abc
re.findall(r'\d+(?=abc)',"1abc")
# 抽取规则: 伴随头晕的过敏
rule_detail = '^(?=.*头晕).*(过敏)'

2.1.9 前向否定界定符。

1
2
3
4
5
6
7
(?!re)

# 只抽取数字,且该数字后面跟的字符不是abc
re.findall(r'\d+(?!abc)',"1abf")

# 不伴随头晕的过敏
rule_detail = '^(?!.*头晕).*(过敏)'

2.1.10 后向否定界定符

1
\(?<!re)

2.1.11 后向肯定界定符

1
\(?>ew)

3 特殊符号

3.1.1 : 匹配字母数字及下划线,等价于 [A-Za-z0-9_]

3.1.2 : 匹配非字母数字及下划线,等价于 [^A-Za-z0-9_]

3.1.3 : 匹配任意空白字符,等价于 [

3.1.4 : 匹配任意非空字符,等价于 [^

3.1.5 匹配任意数字,等价于 [0-9]

3.1.6 : 匹配任意非数字,等价于 [^0-9]

3.1.7 : 匹配字符串开始

3.1.8 : 匹配字符串结束

3.1.9 : 匹配字符串结束,如果存在换行,只匹配到换行前的结束字符串

3.1.10 匹配最后匹配完成的位置

3.1.11 匹配单词边界,即单词和空格间的位置,如:er\b,可匹配 "never" 中的 'er',但不能匹配 "verb" 中的 'er'

3.1.12 : 匹配非单词边界,如:er\B,可匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'

3.1.13 , 等: 匹配换行符,制表符等

3.1.14 \1...\9: 匹配第 n 个分组的内容

3.1.15 [e00-fa5]: 可以匹配任意 UTF-8 编码下的中文字符

4 修饰符

4.1.1 re.I 忽略大小写

4.1.2 re.L 表示特殊字符集 , , , , 依赖于当前环境

4.1.3 re.M 多行模式,影响 ^ 和$

4.1.4 re.S 匹配包括换行在内的所有字符

4.1.5 re.U 表示特殊字符集 , , , , , 依赖于 Unicode 字符属性数据库

4.1.6 re.X 为了增加可读性,忽略空格和 # 后面的注释

5 匹配对象方法

5.1.1 group(num=0): 输入可为多个组号,获取包含组所对应值的元组

5.1.2 groups(): 获取包含所有小组字符串的元组

5.1.3 group([group1, …]): 获取一个或多个分组匹配字符串

5.1.4 start([group]): 获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0

5.1.5 end([group]): 获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引 +1),参数默认值为 0

5.1.6 span([group]): 获取 (start(group), end(group))

5.1.7 groupdict(): 以字典方式返回字符串中多项内容

1
2
m = re.match(r'(?P<user>\w+)@(?P<website>\w+)\.(?P<extension>\w+)','myname@hackerrank.com')
m.groupdict()

6 函数

6.1.1 从起始位置查找

re.match(pattern, string, flags=0): 从字符串的起始位置匹配模式,可以使用 group(num) 或 groups() 获取匹配表达式

pattern: 匹配的正则表达式

string: 要匹配的字符串

flags: 标志位,表示匹配模式,具体参数如下:

1
2
3
4
re.match('www', 'www.baidu.com').span() 
#返回:(0,3)
re.match('com', 'www.baidu.com')
#返回:None

6.1.2 查找匹配字符串

re.search(pattern, string, flags=0): 扫描整个字符串并返回第一个成功的匹配,可以使用 group(num) 或 groups() 获取匹配表达式

1
2
3
4
re.search('www', 'www.baidu.com').span() 
#返回:(0,3)
re.search('com', 'www.baidu.com').span()
#返回:(11,14)

6.1.3 替换字符串

re.sub(pattern, repl, string, count=0, flags=0): 替换字符串中的匹配项

repl: 替换的字符串,也可为一个函数

count: 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配

1
2
3
4
re.sub(r'#.*$', "", "2004-959-559 # 这是电话号码") 
#返回:2004-959-559
re.sub(r'\D', "", "2004-959-559 # 这是电话号码")
#返回:2004959559

repl 特殊写法:

sub 可支持部分替换描述的字符串,当使用括号分组时,用

1
\g<n>

可指定保留第 n 组,

例如,下面语句用于插入数据库前的引号处理:在引号前方加入两个反斜杠,对于已加入反斜杠的引号不做处理。

1
2
string = "直肠肿物Mile's手术"
re.sub(r"([^\\])(')","\g<1>\\'", string)

6.1.4 编译正则表达式

re.compile(pattern[, flags]): 用于编译正则表达式,生成正则表达式对象,使运行速度更快,可供 match() 和 search() 这两个函数使用

6.1.5 查询子串(返回列表)

re.findall(pattern, string[, pos[, endpos]]): 在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果无匹配项,则返回空列表

pos: 指定字符串的起始位置,默认为 0

endpos: 指定字符串的结束位置,默认为字符串的长度

1
2
3
4
result1 = re.findall(r'\d+', 'baidu 123 google 456') 
#返回:\['123', '456']
result2 = re.findall(r'\d+', 'bai88du123google456', 0, 10)
#返回:\['88', '12']

6.1.6 查询子串(返回迭代器)

re.finditer(pattern, string, flags=0): 在字符串中找到正则表达式匹配的所有子串,并把它们作为一个迭代器返回

1
2
3
4
it = re.finditer(r"\d+","12a32bc43jf3") 
for match in it:
print(match.group())
#返回:12,32,43,3

6.1.7 切分字符串

re.split(pattern, string[, maxsplit=0, flags=0]): 按照能够匹配的子串将字符串分割后返回列表

maxsplit: 分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数

1
2
3
4
5
6
7
8
re.split('\W+', 'baidu, baidu, baidu.') 
#返回:\['baidu', 'baidu', 'baidu', '']
re.split('(\W+)', ' baidu, baidu, baidu.')
#返回:\['', ' ', 'baidu', ', ', 'baidu', ', ', 'baidu', '.', '']
re.split('\W+', ' baidu, baidu, baidu.', 1)
#返回:\['', 'baidu, baidu, baidu.']
re.split('a*', 'hello world')
#返回:\['hello world']

7 常用正测

7.1.1 去掉括号中内容

1
re.sub(u"\\(.*?\\)|\\{.*?}|\\[.*?]", "", s)

7.1.2 找中文

1
re.findall('[\u4e00-\u9fa5]', string)

7.1.3 切分中英文

1
[x for x in re.split('([\u4e00-\u9fa5]+)','中文_en拆分') if x != '']