1. 标准库模块 re
Python3中使用re
模块支持正则表达式(Regular Expression),需要定义一个用于匹配的模式(pattern)字符串
,以及一个要匹配的字符串(string)
两种模式:
(1)如果做一次简单的文本匹配/搜索操作的话,可以直接使用 re 模块级别的函数
(2)如果你打算做大量的匹配和搜索操作的话,最好先编译正则表达式,然后再重复使用它
1.1 使用match()从字符串开头开始匹配
格式:返回值 = re.match( ' 正则模式' ,' 字符串 ' )
格式:返回值 = re.compile('正则模式').match('字符串')
如果字符串是以正则表达式开头,则表明匹配成功,返回匹配到的对象,比<_sre.SRE_Match object; span=(0, 2), match='My'>,如果匹配失败,返回None
1.2 使用search()寻找首次匹配
格式:返回值 = re.search( ' 正则模式' ,' 字符串 ' )
格式:返回值 = re.compile('正则模式').search('字符串')
如果字符串中有多个地方与正则表达式匹配的话,search()
方法返回第一次匹配到的结果
1.3 使用findall()或finditer()寻找所有匹配
格式:返回值 = re.findall( ' 正则模式' ,' 字符串 ' )
格式:返回值 = re.compile('正则模式').findall('字符串')
格式:返回值 = re.finditer( ' 正则模式' ,' 字符串 ' )
格式:返回值 = re.compile('正则模式').finditer('字符串')
findall()
方法会搜索文本并以列表形式返回所有的匹配。
如果想以迭代方式返回匹配,可以使用finditer()
方法来代替
1.4 使用sub()替换匹配
格式:返回值 = re.sub('被匹配的模式', '替换模式', '字符串 ' )
2 正则表达式语法
2.1 基本模式
语法 | 说明 | 模式示例 | 匹配 |
---|---|---|---|
普通字符 | 普通的文本值代表自身,用于匹配非特殊字符 | ab |
ab |
. |
匹配除换行符\n 以外的任意一个字符。如果要匹配多行文本,可以指定re.DOTALL 标志位 |
ab. |
匹配abc或abC,不匹配ab,因为b后面一定要有一个字符 |
\ |
转义字符,比如要匹配点号. 本身,需要转义它\. ,如果不转义,. 将有上一行所示的特殊含义 |
ab\. |
匹配ab.com,不匹配abc |
[] |
匹配中括号内的一个字符 1. 中括号内的字符可以全部列出,如[abc] 表示匹配字符a 或b 或c 2. 也可以使用- 表示范围,如[a-z] 表示匹配所以小写字母中的任意一个字符 3. 本文后续要介绍的如* 、+ 等特殊字符在中括号内将失去特殊含义,如[*+()] 表示匹配字符* 或+ 或( 或) 4. 本文后续要介绍的特殊字符集如\d 、\w 等也可以放入此中括号内,继续保持特殊含义 5. 如果中括号内的字符序列前面有一个^ ,表示不匹配中括号内的任何一个字符,如[^0-9] 表示不匹配数字,a[^0-9]c 不匹配a1c ,但会匹配abc 6. 要匹配字符] ,可以转义它,或者把它放在中括号内的首位,如a[()[\]{}]c 或a[]()[{}]c 都可以匹配到a]c
|
a[0-9]b |
a1b或a2 |
2.2 特殊字符集
语法 | 说明 | 模式示例 | 匹配 |
---|---|---|---|
\d | 匹配任意一个数字字符,等价于[0-9] | a\db | a1b |
\D | 匹配任意一个非数字字符,等价于[^0-9] | a\Db | aAb |
\s | 匹配任意一个空白字符,等价于[ \t\n\r\f\v] | a\sb | a b |
\S | 匹配任意一个非空白字符,等价于[^ \t\n\r\f\v] | a\Sb | aAb |
\w | 匹配任意一个 alphanumeric character,等价于[a-zA-Z0-9_] | a\wb | azb或aZb或a1b或a_b |
\W | 匹配任意一个 non-alphanumeric character,等价于[^a-zA-Z0-9_] | a\Wb | a-b或a b |
2.3 数量
说明: 表格中 斜体 的 prev 表示 1. 单个字符如b 2. 或者复杂的表达式如(abc)或(.|\n)(这是分组的功能
语法 | 说明 | 模式示例 | 匹配 |
---|---|---|---|
prev* | 匹配0个或多个 prev,尽可能多地匹配,贪婪模式,等价于{0,} | ab* | a或ab或abb或abbb,注意是匹配字符a后面跟0个或多个字符b |
prev*? | 匹配0个或多个 prev,尽可能少地匹配,非贪婪模式 | ab*? | a,非贪婪模式下匹配0个字符b |
prev+ | 匹配1个或多个 prev,尽可能多地匹配,贪婪模式,等价于{1,} | ab+ | ab或abb或abbb |
prev+? | 匹配1个或多个 prev,尽可能少地匹配,非贪婪模式 | ab+? | ab,非贪婪模式下匹配1个字符b |
prev? | 匹配0个或1个 prev,尽可能多地匹配,贪婪模式,等价于{0,1} | ab? | a或ab |
prev?? | 匹配0个或1个 prev,尽可能少地匹配,非贪婪模式 | ab?? | a,非贪婪模式下匹配0个字符b |
prev{m} | 匹配m个连续的 prev | a{3} | aaa |
prev{m,n} | 匹配m到n个连续的 prev ,尽可能多地匹配,贪婪模式。n可选,如果不指定,则表示m到无穷多个连续的 prev | a{3,5} | aaa或aaaa或aaaaa |
prev{m,n}? | 匹配m到n个连续的 prev ,尽可能少地匹配,非贪婪模式 | a{3,5}? | aaa |
2.4边界
语法 | 说明 | 模式示例 | 匹配 |
---|---|---|---|
^prev | 匹配以 prev 开头的字符串(脱字符)。多行文本中,默认只会匹配第一行的开头位置,如果设置了re.MULTILINE标志位,则也会匹配换行符之后的开头位置 | ^ab | abcd |
prev$ | 匹配以 prev 结尾的字符串。多行文本中,默认 |
ab$ | 只匹配ab。如果是.*ab$则会匹配123ab,否则使用ab\Z |
\b | 单词边界。Matches the empty string, but only at the beginning or end of a word. A word is defined as a sequence of word characters. Note that formally, \b is defined as the boundary between a \w and a \W character (or vice versa), or between \w and the beginning/end of the string. 注意: \b在Python中默认会被转义为\x08表示退格,需要将整个正则表达式指定为原始字符串(在前面加个r),即r'\bfoo\b' | r'\bfoo\b' 请使用re.findall()测试 | 匹配foo或foo.或(foo)或bar foo baz,但不匹配foobar或foo3 |
\B | 非单词边界。Matches the empty string, but only when it is not at the beginning or end of a word. \B is just the opposite of \b. | py\B | 匹配python或py3或py2,但不匹配py或py.或py! |
\A | Matches only at the start of the string. | \Aab | abcde |
\Z | Matches only at the end of the string. | ab\Z | 123ab |
2.5 分组
语法 | 说明 | 模式示例 | 匹配 |
---|---|---|---|
(expr) | 将小括号内的表达式作为一个分组,后面可以接表示数量的特殊字符。每个分组的编号从1开始递增,后续可以使用\1、\2这样引用分组匹配到的内容 | a(bc)?d | ad或abcd,不匹配abcbcd |
expr1 │expr2 | 匹配 expr1 或 expr2 ,a│b│c等价于[abc],都表示匹配字符a或b或c。从左至右,如果匹配了某个表达式,则跳过后续表达式。expr1 │ expr2表示作用于整个待匹配的字符串,而(expr1│expr2)加入小括号内表示分组,不是整个字符串 | p(i│u)g | pig或pug |
\1 | 引用编号为1的分组匹配到的字符串,同理\2表示引用第2个分组。注意: 此时为了不让Python自动将\1转义为\x01,需要将整个正则表达式指定为原始字符串(在前面加个r),即r'a(\d)b\1c' | r'a(\d)b\1c' | a3b3c |
(?P<NAME>expr) | 类似于(expr),同时给分组指定了一个别名NAME,注意是大写的字母P | r'a(?P<quote>\d)b\1c' | a3b3c |
(?P=NAME) | 引用别名为NAME的分组,当然也可以继续使用编号的形式引用分组如\1,此时要加r指定为原始字符串 | a(?P<quote>\d)b(?P=quote)c 或 r'a(?P<quote>\d)b\1c' | a3b3c |
引用命名的分组:
当使用match()
或search()
时,所有的匹配会以m.group()
的形式返回到对象m中。如果你用括号将某一模式包裹起来, 括号中模式匹配得到的结果归入自己的分组group(无名称)
中,而调用 m.groups()
可以得到包含这些匹配的元组
2.6 扩展语法
Python3中的正则表达式,以(?开头的都是一些扩展语法,比如上面学过的(?P<NAME>expr)和(?P=NAME),还有一些常用的:
语法 | 说明 | 模式示例 | 匹配 |
---|---|---|---|
(?:expr) | 非捕获组。如果分组后续要被\1这样的形式引用,使用(expr),这叫捕获组,后面可以接表示数量的特殊字符。如果不想分组被引用,就使用(?:expr),这叫非捕获组,后面可以接表示数量的特殊字符 | a(?:\d)+bc,此时不支持引用分组,像r'a(?:\d)+b\1c'这样的属于语法错误 | a333bc |
prev(?=next) | 如果后面为 next,则返回 prev | ab(?=\d) | 如果ab后面紧跟一个数字,则匹配,比如ab3,返回ab |
prev(?!next) | 如果后面不是 next,则返回 prev | ab(?!\d) | 如果ab后面不是紧跟一个数字,则匹配,比如abc,返回ab |
(?<=prev)next | 如果前面为 prev,则返回 next | (?<=\d)ab | 如果ab前面是一个数字,则匹配,比如1ab,返回ab |
(?<!\d)ab | 如果前面不是 prev,则返回 next | (?<!\d)ab | 如果ab前面不是一个数字,则匹配,比如Aab,返回ab |
Python支持的其它正则表达式的标志位flags:
re.A: 或re.ASCII,使\w/\W/d/\D/\s/\S/\b/\B只匹配ASCII字符,不匹配Unicode字符。
re.I: 或re.IGNORECASE,忽略大小写,[A-Z]会匹配小写字母。
re.M: 或re.MULTILINE,多行模式,改变^或$的默认行为。
re.S: 或re.DOTALL,Make the.special character match any character at all, including a newline; without this flag, .will match anything except a newline。
re.U: 或re.UNICODE,默认使用此标志位,\w/\W/d/\D/\s/\S/\b/\B会匹配Unicode字符,如果指定了re.A标志,则re.U失效。
re.X: 或re.VERBOSE,允许整个正则表达式写成多行,忽略空白字符,并可以添加#开头的注释,这样更美观。
注:.|\n
匹配所有字符,或者指定re.DOTALL
标志位