部分正则语法

=> r"\n" 表示两个字符 \n,而 "\n" 表示一个字符,即换行符。

=> {m,n}? 匹配尽可能少的字符

=> [] 用来表示一组字符,在 [] 中特殊字符失去它们特殊的含义,即 [(+*)] 就匹配 ( + * ) 这四个字符。

=> [^5] 匹配所有不是 5 的字符,[^^] 匹配所有不是 ^ 的字符,在 [] 中,如果 ^ 不是第一个字符,那么它就没有特殊意义。

=> (?aiLmsux) 放在正则表达式前,用来开启正则表达式标志,这个表达式匹配空字符串。其中 ‘a’ 表示 re.A,’i’ 表示 re.I ……

re.match(r'(?i)ab|AB', 'aB')

=> (?:...) 表示不捕获,有时候需要使用括号,但是又不想捕获分组,这个时候可用此法。

=> (?P<name>...) 用来给一个分组进行命名,一个正则表达式中如果有多个分组,尤其是分组之间有嵌套的时候,后向引用分组的时候,使用数字就显得很麻烦且容易出错,而给一个分组命名后,就方便引用了。引用的时候使用 (?P=name) 即可。

re.match(r'(?P<underscore>_{1,2})abc(?P=underscore)', '__abc__')

=> (?#...) 这里表示一个注释,括号中的内容会被忽略。

=> (?=...) 前向断言,如下例子,只匹配后面跟着 defabc

re.match(r'abc(?=def)', 'abcdef')

=> (?!...) 如下,匹配后面不跟 dabc

re.match(r'abc(?!d)', 'abce')

=> (?<=...)(?<!...)

>>> m = re.search('(?<=abc)def', 'abcdef')
>>> m.group(0)
'def'

=> (?(id/name)yes-pattern|no-pattern)

这里 id/name 表示一个分组的编号或者名称,即如果此前这个分组已经匹配到了,那么就匹配 yes-pattern 否则匹配(可选)no-pattern

>>> re.match(r'(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$)', 'wangyu@163.com').group(0)
<<< 'wangyu@163.com'

>>> re.match(r'(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$)', '<wangyu@163.com>').group(0)
<<< '<wangyu@163.com>'

这里如果前面的 < 有匹配上,那么结尾就要匹配一个 > 否则匹配 $

=> \A,匹配字符的开头,这和 ^ 是有差别的,\A 只会匹配一个位置,那就是字符串开头。而 ^ 在多行模式下,可以匹配每一行的开头。

=> \Z 匹配字符的结尾。

=> \b,匹配 \W\w 的边界,如 re.search(r'ABC\b', 'ABC>')

=> \B,匹配 \w\w 或者 \W\W 的边界。

=> \d\D 分别匹配数字和非数字。

=> \s 匹配空白符,即 [\t\n\r\f\v]

=> \S 匹配非空白,即 [^\t\n\r\f\v]

=> \w 匹配字符,ASCII 范围内等价于 [a-zA-Z0-9]

=> \W 匹配非 \w

re 模块

=> re.compile

返回一个正则表达式对象,上面有很多下面介绍的在 re 模块上包含的方法。

re.compile(pattern, flags=0)
<<< r = re.compile(r'<(\d+)>')
<<< r.match('<323>').groups()
>>> ('323',)

=> re.search

在字符中搜索匹配的 pattern,如果有匹配则返回 match object,否则返回 None。

match = re.search(pattern, string)
if match:
    process(match)

=> re.match

如果字符串的开头与 pattern 匹配,则返回 match object,否则返回 None。

re.match(pattern, string, flags=0)

如果整个字符串都匹配,则返回 match object

re.fullmatch(pattern, string, flags=0)

=> re.split,使用正则表达式对字符串进行切分。

re.split(pattern, string, maxsplit=0, flags=0)

如果用于切分的正则表达式中包含分组,那么分组捕获的内容也会返回。

>>> re.split(r'<->', '123<->456<->789')
<<< ['123', '456', '789']

>>> re.split(r'<(-)>', '123<->456<->789')
<<< ['123', '-', '456', '-', '789']

=> re.findall

返回所有匹配的子字符串。

<<< re.findall(r'\d{3}', '123<->456<->789')
>>> ['123', '456', '789']

# 含有多个分组的时候,返回的是元组的列表
<<< re.findall(r'(\d)\d(\d)', '123<->456<->789')
>>> [('1', '3'), ('4', '6'), ('7', '9')]

=> re.finditer

返回 match object 的迭代器,由此可以得到所有的匹配项,用于处理较长的文本。

=> re.sub

这个方法用来从源字符串中匹配部分内容,然后通过一个模板构成新的字符串。

re.subn(pattern, repl, string, count=0, flags=0)

举例子,比如用 123->456 构造出 '456<-123'

pattern 部分匹配 123456,然后 repl 部分使用匹配项,拼凑出目标字符串。

这里 repl 是一个字符串,要想使用 pattern 匹配的分组,可以使用 \1 这样的写法,对于命名分组,可以使用 \g<name> 这样的写法。

>>> re.sub(r'(?P<from>\d{3})->(?P<to>\d{3})', '\g<to><-\g<from>', '123->456')
<<< '456<-123'

Match 对象

=> Match.expand

<<< match = re.search(r'<(?P<name>\w+)@(\w+)\.(\w+)>', '<wangyu@163.com>')
<<< match.expand('mailto:\g<name>[at]\g<2>[dot]\g<3>')
>>> 'mailto:wangyu[at]163[dot]com'

=> Match.group

<<< match = re.search(r'<(?P<name>\w+)@(\w+)\.(\w+)>', '<wangyu@163.com>')
<<< match.group(0) # or match.group()
>>> '<wangyu@163.com>'

<<< match.group(0,1,2,3)
>>> ('<wangyu@163.com>', 'wangyu', '163', 'com')

=> Match.groups

以元组的形式返回所有分组。

<<< match.groups()
>>> ('wangyu', '163', 'com')

=> Match.groupdict

以字典的形式返回所有命名分组,未命名的分组会被忽略。

<<< match = re.search(r'<(?P<name>\w+)@(?P<host>\w+.\w+)>', '<wangyu@163.com>')
<<< match.groupdict()
>>> {'name': 'wangyu', 'host': '163.com'}

=> Match.start / Match.end

返回匹配的分组的起始和结束位置。

<< match = re.search(r'<(?P<name>\w+)@(?P<host>\w+.\w+)>', '<wangyu@163.com>')
<<< match.start(),match.start(1),match.start(2)
>>> (0, 1, 8)

<<< match.end(),match.end(1),match.end(2)
>>> (16, 7, 15)

=> Match.span

返回指定分组的起始和结束位置。

<<< match.span(),match.span(1),match.span(2)
>>> ((0, 16), (1, 7), (8, 15))