Python 中一类主要的处理对象就是字符串,如何从字符串中筛选特定模式的子字符串就需要正则表达式。使用正则表达式的模式和字符串既可以是 Unicode 字符串(str),也可以是 8 为字节串(bytes)。本节介绍如何在 Python 中使用正则表达式。
正则表达式调用格式
1 2 3 4 5 6 7 8 9 10 11 12
| import re
re_exp = re.compile(r'xxx', flags=flag) re_exp.match(str_instance) re_exp.findall(str_instance) re_exp.search(str_instance) re_exp.split(str_instance)
re.match(r'xxx', str_instance, flags=flag) re.findall(r'xxx', str_instance, flags=flag) ...
|
其中,re 是 python 内置的正则表达式模块,r’xxx’ 为匹配模式,flags 为一个可选参数,称为标记,可配置为是否忽略大小写(re.I)、采用多行模式(re.M)等。re.compile 为将匹配模式编译为正则表达式,会被缓存。match, findall 等编译后的正则表达式对象支持的方法和属性(如 re_exp.flags, re_exp.groups, re_exp.pattern等)。
正则表达式语法-匹配模式
正则表达式中有一些特殊语法,具体的如下:
- 绝大部分普通字符(如 ‘A’, ‘a’, ‘0’ 等)是最简单的表达式,匹配自身;除此之外,还有一些特殊字符。
.
默认模式下匹配除了换行以外的任意字符;如 py.
可匹配 ‘pyc’, ‘pyo’, ‘py!’
^
匹配字符串的开头;
$
匹配字符串的结尾;
*
对它前面的正则式匹配 0 到任意次重复,尽量多的匹配字符串,即贪婪匹配;
+
对它前面的正则式匹配 1 到任意次重复;
?
对它前面的正则式匹配 0 到 1 次重复;
*?, +?, ??
因为 *, +, ?
都是贪婪匹配,它们会进行尽可能多的匹配。但有时不需要这种行为,在它们末尾再增加 ?
则转变为非贪婪方式,会尽量少的进行字符匹配;
{m}
对其前面的正则式指定匹配 $m$ 个重复,如果少于 $m$ 个则会导致匹配失败;
{m,n}
对其前面的正则式进行 $m$ 到 $n$ 次匹配,属于贪婪式,会在 $m$ 和 $n$ 之间取尽量多。忽略 $m$ 意指 $m=0$,忽略 $n$ 意指 $n$ 取无穷大。特别注意逗号不能省略,否则无法辨识修饰符应该忽略哪个边界;
{m,n}?
采用非贪婪模式,只匹配 $m$ 和 $n$ 之间尽量少的字符次数;
\
转义字符(允许你匹配上面出现的特殊字符);
[]
表示在中括号里的字符为字符串中出现的可选字符。只匹配中括号中出现的字符。如 [a-f0-9A-F]
匹配十六进制位、[0-5][0-9]
匹配 00 到 59 时间数。如果特殊字符出现在中括号中,则将使特殊字符失去特殊含义,功能同转义字符。[^5]
匹配除了5以外的字符;如果要匹配 ]
,可以采用:1)前面增加转义字符 [()\]]
;2)放在首位 []()]
,其中 ()
为其他需要匹配的字符;
|
或符号,如 A|B
则正则式 A
或 B
;
()
表示将匹配完成的内容截取除小括号中的内容;
\A
只匹配字符串开始;
\b
匹配空字符串,但只能在单词开始或结尾的位置;
\B
匹配空字符串,但不能在单词的开始或结尾的位置,如 r'py\B'
匹配 ‘python’, ‘py3’,但不匹配 ‘py’;
\d
匹配十进制数;如 00\d
可匹配 ‘007’,但无法匹配 ‘00A’
\D
匹配非十进制数;
\s
匹配空白字符;
\S
匹配非空白字符;
\w
匹配词语字符,包含构成词语的绝对部分字符,也包括数字和下划线;如 \w\w\d
可匹配 ‘py3’
\W
匹配非单词字符的字符;
\Z
只匹配字符串尾;
正则表达式 flags 标记
re.A
或 re.ASCII
让 \w, \W, \b, \B, \d, \D, \s, \S
只匹配 ASCII,而不是 Unicode;
re.DEBUG
显示编译时的 debug 信息;
re.I
或 re.IGNORECASE
忽略大小写匹配;如模式 [A-Z]
也只会匹配小写字符;
re.L
或 re.LOCALE
由当前语言区域决定 \w, \W, \b, \B
和大小写敏感匹配;
re.M
或 re.MULTILINE
样式字符 ^
匹配字符串的开始,和每一行的开始(换行符后面紧跟的符号)、样式字符 $
匹配字符串尾,和每一行的结尾(换行符前面那个符号)。注意,默认情况下 ^
只匹配字符串开头,$
只匹配字符串结尾;
re.S
或 re.DOTALL
让 .
匹配换行符,默认情况下,.
只匹配除了换行符以外的其他任意字符;
re.X
或 re.VERBOSE
这个标记允许你编写更具可读性更友好的正则表达式。通过分段和添加注释。
正则表达式函数
re.search(pattern, string, flags=0)
扫描整个 字符串 string 找到匹配样式的第一个位置,并返回一个相应的匹配对象。如果没有匹配,就返回一个 None
; 注意这和找到一个零长度匹配是不同的;
re.match(pattern, string, flags=0)
只从 string 的开始匹配到了正则表达式样式,就返回一个相应的匹配对象 。 如果没有匹配,就返回 None
;注意它跟零长度匹配是不同的。注意即便是 MULTILINE
多行模式, re.match()
也只匹配字符串的开始位置,而不匹配每行开始。如果你想定位 string 的任何位置,使用 search()
来替代;
re.fullmatch(pattern, string, flags=0)
如果整个 string 匹配到正则表达式样式,就返回一个相应的 匹配对象 。 否则就返回一个 None
;注意这跟零长度匹配是不同的;
re.split(pattern, string, maxsplit=0, flags=0)
用 pattern 分开 string。如果在 pattern 中捕获到括号,那么所有的组里的文字也会包含在列表里。如果 maxsplit 非零, 最多进行 maxsplit 次分隔, 剩下的字符全部返回到列表的最后一个元素;
re.findall(pattern, string, flags=0)
以列表形式返回所有匹配到的子字符串;
re.finditer(pattern, string, flags=0)
pattern 在 string 里所有的非重复匹配,返回为一个迭代器 iterator 保存了匹配对象。 string 从左到右扫描,匹配按顺序排列。空匹配也包含在结果里;
re.sub(pattern, repl, string, count=0, flags=0)
返回通过使用 repl 替换在 string 最左边非重叠出现的 pattern 而获得的字符串。 如果样式没有找到,则不加改变地返回 string。 repl 可以是字符串或函数;如为字符串,则其中任何反斜杠转义序列都会被处理;
re.subn(pattern, repl, string, count=0, flags=0)
行为与 sub()
相同,但是返回一个元组 (字符串, 替换次数)
;
re.escape(pattern)
转义 pattern 中的特殊字符。如果你想对任意可能包含正则表达式元字符的文本字符串进行匹配,它就是有用的;
re.purge()
清除正则表达式的缓存。
示例
1 2
| re.split(r'\s+', 'a b c') ['a', 'b', 'c']
|
1 2
| re.split(r'[\s\,]+', 'a,b, c d') ['a', 'b', 'c', 'd']
|
1 2
| re.split(r'[\s\,\;]+', 'a,b;; c d') ['a', 'b', 'c', 'd']
|
1 2
| re.findall(r"(\w+)=(\d+)", "set width=20 and height=10") [('width', '20'), ('height', '10')]
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| text='datetime:11/28/2022'
datepat=re.compile(r'(\d+)/(\d+)/(\d+)')
print(datepat.sub(r'\3-\1-\2', text)) print(text)
datetime:2022-11-28 datetime:11/28/2022
print(datepat.sub(r'\1/\3', text)) print(text)
|
参考文献
- 正则表达式
re
— 正则表达式操作