学习自:https://docs.python.org/zh-cn/3/library/re.html#module-re
python的正则表达式有两种使用方法,第一种是直接用re模块的函数。
一、re.search(pattern, string, flag=0)
扫描整个字符串,找到第一个能匹配的地方,返回一个匹配对象,如果失败,返回None。
str = "abc123def456[qqq]{qqq}<qqq>!@#abcabcabc"
print(re.search("qqq", str)) # <re.Match object; span=(13, 16), match='qqq'>
print(re.search("^qqq", str)) # None
二、re.match(pattern, string, flag=0)
从字符串开头开始匹配,返回一个匹配对象,如果失败,返回None。
str = "abc123def456[qqq]{qqq}<qqq>!@#abcabcabc"
print(re.match("qqq", str)) # None
print(re.match("\w+", str)) # <re.Match object; span=(0, 12), match='abc123def456'>
三、re.fullmatch(pattern, string, flags=0)
匹配整个字符串,返回一个匹配对象,如果失败,返回None。
str = "abc123def456[qqq]{qqq}<qqq>!@#abcabcabc"
print(re.fullmatch("\w+", str)) # None
print(re.fullmatch(".+", str)) # <re.Match object; span=(0, 39), match='abc123def456[qqq]{qqq}<qqq>!@#abcabcabc'>
四、re.split(pattern, string, maxsplit=0, flags=0)
用pattern把string分开,返回一个列表,如果pattern里用括号括起来了,括号里匹配到的也会作为列表的一个元素
str = "abc123def456[qqq]{qqq}<qqq>!@#abcabcabc"
print(re.split("(.)qqq(.)", str))
# ['abc123def456', '[', ']', '', '{', '}', '', '<', '>', '!@#abcabcabc']
五、re.findall(pattern, string, flags=0)
返回匹配到的所有元素组成的列表
str = "abc123def456[qqq]{qqq}<qqq>!@#abcabcabc"
print(re.findall("\d+", str)) # ['123', '456']
六、re.finditer(pattern, string, flags=0)
返回一个保存了匹配对象的迭代器
str = "abc123def456[qqq]{qqq}<qqq>!@#abcabcabc"
print(re.finditer("\w+", str))
for a in re.finditer("\w+", str):
print(a)
# <callable_iterator object at 0x000002A6D25F66A0>
# <re.Match object; span=(0, 12), match='abc123def456'>
# <re.Match object; span=(13, 16), match='qqq'>
# <re.Match object; span=(18, 21), match='qqq'>
# <re.Match object; span=(23, 26), match='qqq'>
# <re.Match object; span=(30, 39), match='abcabcabc'>
七、re.sub(pattern, repl, string, count=0, flags=0)
- 返回通过使用 repl 替换在 string 最左边非重叠出现的 pattern 而获得的字符串。
str = "abcd"
print(re.sub("a", "1", str)) # 1bcd
- 如果样式没有找到,则不加改变地返回 string
str = "abcd"
print(re.sub("e", "1", str)) # abcd
- repl 可以是字符串或函数;如为字符串,则其中任何反斜杠转义序列都会被处理。
repl是字符串,而不是正则表达式。可以识别
\n
\t
之类的,但是不能识别\w
\s
str = "abcd"
print(re.sub("b", "\t", str)) # a cd
- 未知的 ASCII 字符转义序列保留在未来使用,会被当作错误来处理。 其他未知转义序列例如
\&
会保持原样。
暂时找不到例子,不太清楚具体意思和现象
- 向后引用像是
\6
会用样式中第 6 组所匹配到的子字符串来替换。
如下的例子,"(abc)\w+.(\w+)]“会匹配到"abc123def456[qqq]“后面的”\2"会替换成前面第二个括号匹配到的"qqq”。
这里写两个反斜杠是因为\2本身有自己的含义,但是具体是什么意思也没查到。或者写
r"\2"
,这时候反斜杠就不会被当做转义符了
str = "abc123def456[qqq]{qqq}<qqq>!@#abcabcabc"
print(re.sub("(abc)\w+.(\w+)\]", "\\2", str)) # qqq{qqq}<qqq>!@#abcabcabc
- 如果 repl 是一个函数,那它会对每个非重复的 pattern 的情况调用。这个函数只能有一个 匹配对象 参数,并返回一个替换后的字符串。
官方的例子长这样
def dashrepl(matchobj):
if matchobj.group(0) == '-':
return ' '
else:
return '-'
print(re.sub('-{1,2}', dashrepl, 'pro----gram-files')) # pro--gram-files
从这个例子可以看到,函数的入参是一个匹配对象,改一下看看入参的样子。
def dashrepl(matchobj):
print(matchobj)
if matchobj.group(0) == '-':
return ' '
else:
return '-'
print(re.sub('-{1,2}', dashrepl, 'pro----gram-files'))
# <re.Match object; span=(3, 5), match='--'>
# <re.Match object; span=(5, 7), match='--'>
# <re.Match object; span=(11, 12), match='-'>
# pro--gram-files
- 可选参数 count 是要替换的最大次数;count 必须是非负整数。如果省略这个参数或设为 0,所有的匹配都会被替换。
def dashrepl(matchobj):
print(matchobj)
if matchobj.group(0) == '-':
return ' '
else:
return '-'
print(re.sub('-{1,2}', dashrepl, 'pro----gram-files', count=2))
# <re.Match object; span=(3, 5), match='--'>
# <re.Match object; span=(5, 7), match='--'>
# pro--gram-files
八、re.subn(pattern, repl, string, count=0, flags=0)
行为与 sub()
相同,但是返回一个元组 (字符串, 替换次数)
.
def dashrepl(matchobj):
print(matchobj)
if matchobj.group(0) == '-':
return ' '
else:
return '-'
print(re.subn('-{1,2}', dashrepl, 'pro----gram-files', count=2))
# <re.Match object; span=(3, 5), match='--'>
# <re.Match object; span=(5, 7), match='--'>
# ('pro--gram-files', 2)
九、re.escape(pattern)
转义 pattern 中的特殊字符。
print(re.escape("http://www.python.org"))
# http://www\.python\.org
十、re.purge()
清除正则表达式的缓存。
十一、flags参数
-
re.A
re.ASCII
让
\w
,\W
,\b
,\B
,\d
,\D
,\s
和\S
只匹配ASCII,而不是Unicode。这只对Unicode样式有效,会被byte样式忽略。相当于前面语法中的内联标志(?a)
。 注意,为了保持向后兼容,re.U
标记依然存在(还有他的同义re.UNICODE
和嵌入形式(?u)
) , 但是这些在 Python 3 是冗余的,因为默认字符串已经是Unicode了(并且Unicode匹配不允许byte出现)。 -
re.DEBUG
显示编译时的debug信息,没有内联标记。
-
re.I
re.IGNORECASE
进行忽略大小写匹配;表达式如
[A-Z]
也会匹配小写字符。Unicode匹配(比如Ü
匹配ü
)同样有用,除非设置了re.ASCII
标记来禁用非ASCII匹配。当前语言区域不会改变这个标记,除非设置了re.LOCALE
标记。这个相当于内联标记(?i)
。注意,当设置了
IGNORECASE
标记,搜索Unicode样式[a-z]
或[A-Z]
的结合时,它将会匹配52个ASCII字符和4个额外的非ASCII字符: ‘İ’ (U+0130, 拉丁大写的 I 带个点在上面), ‘ı’ (U+0131, 拉丁小写没有点的 I ), ‘ſ’ (U+017F, 拉丁小写长 s) and ‘K’ (U+212A, 开尔文符号).如果使用ASCII
标记,就只匹配 ‘a’ 到 ‘z’ 和 ‘A’ 到 ‘Z’ 。 -
re.L
re.LOCALE
由当前语言区域决定
\w
,\W
,\b
,\B
和大小写敏感匹配。这个标记只能对byte样式有效。这个标记不推荐使用,因为语言区域机制很不可靠,它一次只能处理一个 "习惯”,而且只对8位字节有效。Unicode匹配在Python 3 里默认启用,并可以处理不同语言。 这个对应内联标记(?L)
。在 3.6 版更改:
re.LOCALE
只能用于byte样式,而且不能和re.ASCII
一起用。在 3.7 版更改: 设置了
re.LOCALE
标记的编译正则对象不再在编译时依赖语言区域设置。语言区域设置只在匹配的时候影响其结果。 -
re.M
re.MULTILINE
设置以后,样式字符
'^'
匹配字符串的开始,和每一行的开始(换行符后面紧跟的符号);样式字符'$'
匹配字符串尾,和每一行的结尾(换行符前面那个符号)。默认情况下,’^’
匹配字符串头,'$'
匹配字符串尾。对应内联标记(?m)
。 -
re.S
re.DOTALL
让
'.'
特殊字符匹配任何字符,包括换行符;如果没有这个标记,'.'
就匹配 除了 换行符的其他任意字符。对应内联标记(?s)
。 -
re.X
re.VERBOSE
这个标记允许你编写更具可读性更友好的正则表达式。通过分段和添加注释。空白符号会被忽略,除非在一个字符集合当中或者由反斜杠转义,或者在
*?
,(?:
or(?P<…>
分组之内。当一个行内有#
不在字符集和转义序列,那么它之后的所有字符都是注释。意思就是下面两个正则表达式等价地匹配一个十进制数字:
a = re.compile(r"""\d + # the integral part
\. # the decimal point
\d * # some fractional digits""", re.X)
b = re.compile(r"\d+\.\d*")