pythonRE 正则匹配表达式
正则表达式可以包含⼀些可选标志修饰符来控制匹配的模式。修饰符被指定为⼀个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:
修饰符
描述re.I
使匹配对⼤⼩写不敏感re.L
做本地化识别(locale-aware )匹配re.M
多⾏匹配,影响 ^ 和 $re.S
使 . 匹配包括换⾏在内的所有字符re.U
根据Unicode 字符集解析字符。这个标志影响 \w, \W, \b, \B.re.X
该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。
例如:
模式字符串使⽤特殊的语法来表⽰⼀个正则表达式:
字母和数字表⽰他们⾃⾝。⼀个正则表达式模式中的字母和数字匹配同样的字符串。
多数字母和数字前加⼀个反斜杠时会拥有不同的含义。
标点符号只有被转义时才匹配⾃⾝,否则它们表⽰特殊的含义。
反斜杠本⾝需要使⽤反斜杠转义。
由于正则表达式通常都包含反斜杠,所以你最好使⽤原始字符串来表⽰它们。模式元素(如 r'/t',等价于'//t')匹配相应的特殊字符。
下表列出了正则表达式模式语法中的特殊元素。如果你使⽤模式的同时提供了可选的标志参数,某些模式元素的含义会改变。
模式
描述^
匹配字符串的开头$
匹配字符串的末尾。.
匹配任意字符,除了换⾏符,当re.DOTALL 标记被指定时,则可以匹配包括换⾏符的任意字符。[...]
⽤来表⽰⼀组字符,单独列出:[amk] 匹配 'a','m'或'k'[^...]
不在[]中的字符:[^abc] 匹配除了a,b,c 之外的字符。re*
匹配0个或多个的表达式。re+
匹配1个或多个的表达式。re?
匹配0个或1个由前⾯的正则表达式定义的⽚段,⾮贪婪⽅式re{ n}
re{ n,}
精确匹配n 个前⾯表达式。re{ n, m}匹配 n 到 m 次由前⾯的正则表达式定义的⽚段,贪婪⽅式a
b (re)
G 匹配括号内的表达式,也表⽰⼀个组(?imx)
正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。(?-imx)
正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。(?: re)
类似 (...), 但是不表⽰⼀个组(?imx:
re)
在括号中使⽤i, m, 或 x 可选标志(?-imx:
re)
在括号中不使⽤i, m, 或 x 可选标志(?#...)
注释.(?= re)
前向肯定界定符。如果所含正则表达式,以 ... 表⽰,在当前位置成功匹配时成功,否则失败。但⼀旦所含表达式已经尝试,匹配引擎根本没有提⾼;模式的剩余部分还要尝试界定符的右边。(?! re)
前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功(?> re)
匹配的独⽴模式,省去回溯。\w
匹配字母数字\W
匹配⾮字母数字\s
匹配任意空⽩字符,等价于 [\t\n\r\f].\S
匹配任意⾮空字符\d
匹配任意数字,等价于 [0-9].\D
匹配任意⾮数字\A
匹配字符串开始\Z
匹配字符串结束,如果是存在换⾏,只匹配到换⾏前的结束字符串。\z
匹配字符串结束\G
匹配最后匹配完成的位置。\b
匹配⼀个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。\B
匹配⾮单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。\n, \t, 等.匹配⼀个换⾏符。匹配⼀个制表符。等
\1...\9
匹配第n 个分组的⼦表达式。\10匹配第n 个分组的⼦表达式,如果它经匹配。否则指的是⼋进制字符码的表达式。正则表达式实例
字符类:
实例
描述[Pp]ython 匹配 "Python" 或 "python"
import re
re.match #从开始位置开始匹配,如果开头没有则⽆
re.search #搜索整个字符串
re.findall #搜索整个字符串,返回⼀个list
# 尝试从字符串起始位置匹配⼀个模式;如果不是起始位置匹配成功,则 re.match() 返回none.匹配成功,re.match() 返回⼀个匹配的对象,否则返回None.
# re.search(pattern, string, flags=0)扫描整个字符串并返回第⼀个成功的匹配.匹配成功, re.search()返回⼀个匹配的对象,否则返回None.
re.sub(pattern, repl, string, count=0, flags=0)
替换字符串中的匹配项.
pattern - 正则中的模式字符串
repl - 替换的字符串,也可为⼀个函数
string - 要被查替换的原始字符串
count - 模式匹配后替换的最⼤次数,默认 0 表⽰替换所有的匹配
re.search(r'[a-z]+','liuyaN1234ab9').group() #返回'liuya'
re.search(r'[a-z]+','liuyaN1234ab9', re.I).group() #返回'liuyaN',对⼤⼩写不敏感
#⽤空格分割
re.split(r'\s+', 'a b c')
返回:['a', 'b', 'c', 'd']
#⽤逗号分隔
re.split(r'[\s\,]+', 'a,b, c d')
返回:['a', 'b', 'c', 'd']
rub[ye]匹配 "ruby" 或 "rube"
实例描述
[aeiou]匹配中括号内的任意⼀个字母
[0-9]匹配任何数字。类似于 [0123456789]
[a-z]匹配任何⼩写字母
[A-Z]匹配任何⼤写字母
[a-zA-Z0-9]匹配任何字母及数字
[^aeiou]除了aeiou字母以外的所有字符
[^0-9]匹配除了数字外的字符
特殊字符类
实例描述
.匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使⽤象 '[.\n]' 的模式。
\d匹配⼀个数字字符。等价于 [0-9]。
\D匹配⼀个⾮数字字符。等价于 [^0-9]。
\s匹配任何空⽩字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S匹配任何⾮空⽩字符。等价于 [^ \f\n\r\t\v]。
\w匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。
\W匹配任何⾮单词字符。等价于 '[^A-Za-z0-9_]'。
基本规则
‘[‘ ‘]’ 字符集合设定符
⾸先说明⼀下字符集合设定的⽅法。由⼀对⽅括号括起来的字符,表明⼀个字符集合,能够匹配包含在其中的任意⼀个字符。⽐如 [abc123] ,表明字符 ’a’ ‘b’ ‘c’ ‘1’ ‘2’ ‘3’ 都符合它的要求。可以被匹配。
在 ’[‘ ‘]’ 中还可以通过 ’-‘ 减号来指定⼀个字符集合的范围,⽐如可以⽤ [a-zA-Z] 来指定所以英⽂字母的⼤⼩写,因为英⽂字母是按照从⼩到⼤的顺序来排的。你不可以把⼤⼩的顺序颠倒了,⽐如写成 [z-a] 就不对了。
如果在 ’[‘ ‘]’ ⾥⾯的开头写⼀个 ‘^’ 号,则表⽰取⾮,即在括号⾥的字符都不匹配。如 [^a-zA-Z] 表明不匹配所有英⽂字母。但是如果 ‘^’ 不在开头,则它就不再是表⽰取⾮,⽽表⽰其本⾝,如 [a-z^A-Z] 表明匹配所有的英⽂字母和字符 ’^’ 。
‘|’ 或规则
将两个规则并列起来,以‘ | ’连接,表⽰只要满⾜其中之⼀就可以匹配。⽐如
[a-zA-Z]|[0-9] 表⽰满⾜数字或字母就可以匹配,这个规则等价于 [a-zA-Z0-9]
注意:关于 ’|’ 要注意两点:
第⼀,它在 ’[‘ ‘]’ 之中不再表⽰或,⽽表⽰他本⾝的字符。如果要在 ’[‘ ‘]’ 外⾯表⽰⼀个 ’|’ 字符,必须⽤反斜杠引导,即 ’/|’ ;
第⼆,它的有效范围是它两边的整条规则,⽐如‘ dog|cat’ 匹配的是‘ dog’ 和 ’cat’ ,⽽不是 ’g’ 和 ’c’ 。如果想限定它的有效范围,必需使⽤⼀个⽆捕获组 ‘(?: )’ 包起来。⽐如要匹配 ‘ I have a dog’ 或 ’I have a cat’ ,需要写成 r’I have a ‘.’ 匹配所有字符
匹配除换⾏符 ’/n’ 外的所有字符。如果使⽤了 ’S’ 选项,匹配包括 ’/n’ 的所有字符。
例:
>>> s=’123 /n456 /n789’
>>> findall(r‘.+’,s)
['123', '456', '789']
>>> re.findall(r‘.+’ , s , re.S)
['123/n456/n789']
‘^’ 和 ’$’ 匹配字符串开头和结尾
注意 ’^’ 不能在‘ [ ] ’中,否则含意就发⽣变化,具体请看上⾯的 ’[‘ ‘]’ 说明。在多⾏模式下,它们可以匹配每⼀⾏的⾏⾸和⾏尾。具体请看后⾯ compile 函数说明的 ’M’ 选项部分
‘/d’ 匹配数字
这是⼀个以 ’/’ 开头的转义字符, ’/d’ 表⽰匹配⼀个数字,即等价于 [0-9]
‘/D’ 匹配⾮数字
这个是上⾯的反集,即匹配⼀个⾮数字的字符,等价于 [^0-9] 。注意它们的⼤⼩写。下⾯我们还将看到 Python 的正则规则中很多转义字符的⼤⼩写形式,代表互补的关系。这样很好记。
‘/w’ 匹配字母和数字
匹配所有的英⽂字母和数字,即等价于 [a-zA-Z0-9] 。
‘/W’ 匹配⾮英⽂字母和数字
即 ’/w’ 的补集,等价于 [^a-zA-Z0-9] 。
‘/s’ 匹配间隔符
即匹配空格符、制表符、回车符等表⽰分隔意义的字符,它等价于 [ /t/r/n/f/v] 。(注意最前⾯有个空格 )
‘/S’ 匹配⾮间隔符
即间隔符的补集,等价于 [^ /t/r/n/f/v]
‘/A’ 匹配字符串开头
匹配字符串的开头。它和 ’^’ 的区别是, ’/A’ 只匹配整个字符串的开头,即使在 ’M’ 模式下,它也不会匹配其它⾏的很⾸。
‘/Z’ 匹配字符串结尾
匹配字符串的结尾。它和 ’$’ 的区别是, ’/Z’ 只匹配整个字符串的结尾,即使在 ’M’ 模式下,它也不会匹配其它各⾏的⾏尾。
例:
>>> s= '12 34/n56 78/n90'
>> re.findall( r'^/d+' , s , re.M ) # 匹配位于⾏⾸的数字
['12', '56', '90']
>>> re.findall( r’/A/d+’, s , re.M ) # 匹配位于字符串开头的数字
['12']
>>> re.findall( r'/d+$' , s , re.M ) # 匹配位于⾏尾的数字
['34', '78', '90']
>>> re.findall( r’/d+/Z’ , s , re.M ) # 匹配位于字符串尾的数字
['90']
‘/b’ 匹配单词边界
它匹配⼀个单词的边界,⽐如空格等,不过它是⼀个‘ 0 ’长度字符,它匹配完的字符串不会包括那个分界的字符。⽽如果⽤ ’/s’ 来匹配的话,则匹配出的字符串中会包含那个分界符。
例:
>>> s = 'abc abcde bc bcd'
>>> re.findall( r’/bbc/b’ , s ) # 匹配⼀个单独的单词 ‘bc’ ,⽽当它是其它单词的⼀部分的时候不匹配
['bc'] #只到了那个单独的 ’bc’
>>> re.findall( r’/sbc/s’ , s ) #匹配⼀个单独的单词 ‘bc’
[' bc '] # 只到那个单独的 ’bc’ ,不过注意前后有两个空格,可能有点看不清楚
‘/B’ 匹配⾮边界
和 ’/b’ 相反,它只匹配⾮边界的字符。它同样是个 0 长度字符。
接上例:
>>> re.findall( r’/Bbc/w+’ , s ) # 匹配包含 ’bc’ 但不以 ’bc’ 为开头的单词
['bcde'] # 成功匹配了 ’abcde’ 中的 ’bcde’ ,⽽没有匹配 ’bcd’
**‘(?:)’ ⽆捕获组**
当你要将⼀部分规则作为⼀个整体对它进⾏某些操作,⽐如指定其重复次数时,你需要将这部分规则⽤ ’(?:’ ‘)’ 把它包围起来,⽽不能仅仅只⽤⼀对括号,那样将得到绝对出⼈意料的结果。
例:匹配字符串中重复的 ’ab’
>>> s=’ababab abbabb aabaab’
>>> re.findall( r’/b(?:ab)+/b’ , s )
['ababab']
如果仅使⽤⼀对括号,看看会是什么结果:
>>> re.findall( r’/b(ab)+/b’ , s )
['ab']
这是因为如果只使⽤⼀对括号,那么这就成为了⼀个组 (group) 。组的使⽤⽐较复杂,将在后⾯详细讲解。
**‘(?# )’ 注释**
Python 允许你在正则表达式中写⼊注释,在 ’(?#’ ‘)’ 之间的内容将被忽略。
(?iLmsux) 编译选项指定
Python 的正则式可以指定⼀些选项,这个选项可以写在 findall 或 compile 的参数中,也可以写在正则式⾥,成为正则式的⼀部分。这在某些情况下会便利⼀些。具体的选项含义请看后⾯的 compile 函数的说明。
此处编译选项 ’i’ 等价于 IGNORECASE ,L 等价于 LOCAL ,m 等价于 MULTILINE , s 等价于 DOTALL , u 等价于 UNICODE , x 等价于 VERBOSE 。
请注意它们的⼤⼩写。在使⽤时可以只指定⼀部分,⽐如只指定忽略⼤⼩写,可写为 ‘(?i)’ ,要同时忽略⼤⼩写并使⽤多⾏模式,可以写为 ‘(?im)’ 。
另外要注意选项的有效范围是整条规则,即写在规则的任何地⽅,选项都会对全部整条正则式有效。
重复
正则式需要匹配不定长的字符串,那就⼀定需要表⽰重复的指⽰符。 Python 的正则式表⽰重复的功能很丰富灵活。重复规则的⼀般的形式是在⼀条字符规则后⾯紧跟⼀个表⽰重复次数的规则,已表明需要重复前⾯的规则⼀定的次数。重复规则有:‘*’ 0 或多次匹配
表⽰匹配前⾯的规则 0 次或多次。
‘+’ 1 次或多次匹配
表⽰匹配前⾯的规则⾄少 1 次,可以多次匹配
例:匹配以下字符串中的前⼀部分是字母,后⼀部分是数字或没有的变量名字
>>> s = ‘ aaa bbb111 cc22cc 33dd ‘
>>> re.findall( r’/b[a-z]+/d*/b’ , s ) # 必须⾄少 1 个字母开头,以连续数字结尾或没有数字
['aaa', 'bbb111']
注意上例中规则前后加了表⽰单词边界的 ’/b’ 指⽰符,如果不加的话结果就会变成:
>>> re.findall( r’[a-z]+/d*’ , s )
['aaa', 'bbb111', 'cc22', 'cc', 'dd'] # 把单词给拆开了
⼤多数情况下这不是我们期望的结果。
‘?’ 0 或 1 次匹配
只匹配前⾯的规则 0 次或 1 次。
例,匹配⼀个数字,这个数字可以是⼀个整数,也可以是⼀个科学计数法记录的数字,⽐如 123 和 10e3 都是正确的数字。
>>> s = ‘ 123 10e3 20e4e4 30ee5 ‘
>>> re.findall( r’ /b/d+[eE]?/d*/b’ , s )
['123', '10e3']
它正确匹配了 123 和 10e3, 正是我们期望的。注意前后的 ’/b’ 的使⽤,否则将得到不期望的结果。
前向界定与后向界定
有时候需要匹配⼀个跟在特定内容后⾯的或者在特定内容前⾯的字符串, Python 提供⼀个简便的前向界定和后向界定功能,或者叫前导指定和跟从指定功能。它们是:
‘(?<=…)’ 前向界定
括号中 ’…’ 代表你希望匹配的字符串的前⾯应该出现的字符串。
‘(?=…)’ 后向界定
括号中的 ’…’ 代表你希望匹配的字符串后⾯应该出现的字符串。
例:你希望出 c 语⾔的注释中的内容,它们是包含在 ’/*’ 和 ’*/’ 之间,不过你并不希望匹配的结果把 ’/*’ 和 ’*/’ 也包括进来,那么你可以这样⽤:
>>> s=r’/* comment 1 */ code /* comment 2 */’
>>> re.findall( r’(?<=//*).+?(?=/*/)’ , s )
[' comment 1 ', ' comment 2 ']
注意这⾥我们仍然使⽤了最⼩匹配,以避免把整个字符串给匹配进去了。
要注意的是,前向界定括号中的表达式必须是常值,也即你不可以在前向界定的括号⾥写正则式。⽐如你如果在下⾯的字符串中想到被字母夹在中间的数字,你不可以⽤前向界定:
例:
>>> s = ‘aaa111aaa , bbb222 , 333ccc ‘
>>> re.findall( r’(?<=[a-z]+)/d+(?=[a-z]+)' , s ) # 错误的⽤法
它会给出⼀个错误信息:
error: look-behind requires fixed-width pattern
不过如果你只要出后⾯接着有字母的数字,你可以在后向界定写正则式:
>>> re.findall( r’/d+(?=[a-z]+)’, s )
['111', '333']
如果你⼀定要匹配包夹在字母中间的数字,你可以使⽤组( group )的⽅式
>>> re.findall (r'[a-z]+(/d+)[a-z]+' , s )
['111']
组的使⽤将在后⾯详细讲解。
除了前向界定前向界定和后向界定外,还有前向⾮界定和后向⾮界定,它的写法为:
‘(?<!...)’ 前向⾮界定
只有当你希望的字符串前⾯不是’…’ 的内容时才匹配
‘(?!...)’ 后向⾮界定
只有当你希望的字符串后⾯不跟着 ’…’ 内容时才匹配。
接上例,希望匹配后⾯不跟着字母的数字
>>> re.findall( r’/d+(?!/w+)’ , s )
['222']
注意这⾥我们使⽤了 /w ⽽不是像上⾯那样⽤ [a-z] ,因为如果这样写的话,结果会是:
>>> re.findall( r’/d+(?![a-z]+)’ , s )
['11', '222', '33']
这和我们期望的似乎有点不⼀样。它的原因,是因为 ’111’ 和 ’222’ 中的前两个数字也是满⾜这个要求的。因此可看出,正则式的使⽤还是要相当⼩⼼的,因为我开始就是这样写的,看到结果后才明⽩过来。不过 Python 试验起来很⽅便,这也是脚本组的基本知识
上⾯我们已经看过了 Python 的正则式的很多基本⽤法。不过如果仅仅是上⾯那些规则的话,还是有很多情况下会⾮常⿇烦,⽐如上⾯在讲前向界定和后向界定时,取夹在字母中间的数字的例⼦。⽤前⾯讲过的规则都很难达到⽬的,但是⽤了组以后‘(‘’)’ ⽆命名组
最基本的组是由⼀对圆括号括起来的正则式。⽐如上⾯匹配包夹在字母中间的数字的例⼦中使⽤的 (/d+) ,我们再回顾⼀下这个例⼦:
>>> s = ‘aaa111aaa , bbb222 , 333ccc ‘
>>> re.findall (r'[a-z]+(/d+)[a-z]+' , s )
['111']
可以看到 findall 函数只返回了包含在 ’()’ 中的内容,⽽虽然前⾯和后⾯的内容都匹配成功了,却并不包含在结果中。
除了最基本的形式外,我们还可以给组起个名字,它的形式是
‘(?P<name>…)’ 命名组
‘(?P’ 代表这是⼀个 Python 的语法扩展 ’<…>’ ⾥⾯是你给这个组起的名字,⽐如你可以给⼀个全部由数字组成的组叫做 ’num’ ,它的形式就是 ’(?P<num>/d+)’ 。起了名字之后,我们就可以在后⾯的正则式中通过名字调⽤这个组,它的形式是
‘(?P=name)’ 调⽤已匹配的命名组
要注意,再次调⽤的这个组是已被匹配的组,也就是说它⾥⾯的内容是和前⾯命名组⾥的内容是⼀样的。
我们可以看更多的例⼦:请注意下⾯这个字符串各⼦串的特点。
>>> s='aaa111aaa,bbb222,333ccc,444ddd444,555eee666,fff777ggg'
我们看看下⾯的正则式会返回什么样的结果:
>>> re.findall( r'([a-z]+)/d+([a-z]+)' , s ) # 出中间夹有数字的字母
[('aaa', 'aaa'), ('fff', 'ggg')]
>>> re.findall( r '(?P<g1>[a-z]+)/d+(?P=g1)' , s ) # 出被中间夹有数字的前后同样的字母
['aaa']
>>> re.findall( r'[a-z]+(/d+)([a-z]+)' , s ) # 出前⾯有字母引导,中间是数字,后⾯是字母的字符串中的中间的数字和后⾯的字母
[('111', 'aaa'), ('777', 'ggg')]
我们可以通过命名组的名字在后⾯调⽤已匹配的命名组,不过名字也不是必需的。
‘/number’ 通过序号调⽤已匹配的组
正则式中的每个组都有⼀个序号,序号是按组从左到右,从 1 开始的数字,你可以通过下⾯的形式来调⽤已匹配的组
⽐如上⾯出被中间夹有数字的前后同样的字母的例⼦,也可以写成:
>>> re.findall( r’([a-z]+)/d+/1’ , s )
['aaa']
结果是⼀样的。
我们再看⼀个例⼦
>>> s='111aaa222aaa111 , 333bbb444bb33'
>>> re.findall( r'(/d+)([a-z]+)(/d+)(/2)(/1)' , s ) # 出完全对称的数字-字母-数字-字母-数字中的数字和字母
[('111', 'aaa', '222', 'aaa', '111')]
Python2.4 以后的 re 模块,还加⼊了⼀个新的条件匹配功能
‘(?( id/name )yes-pattern|no-pattern)’ 判断指定组是否已匹配,执⾏相应的规则
这个规则的含义是,如果 id/name 指定的组在前⾯匹配成功了,则执⾏ yes-pattern 的正则式,否则执⾏ no-pattern 的正则式。
举个例⼦,⽐如要匹配⼀些形如 usr@mail 的邮箱地址,不过有的写成 < usr@mail > 即⽤⼀对 <> 括起来,有点则没有,要匹配这两种情况,可以这样写
>>> s='<usr1@mail1> usr2@maill2'
>>> re.findall( r'(<)?/s*(/w+@/w+)/s*(?(1)>)' , s )
[('<', 'usr1@mail1'), ('', 'usr2@maill2')]
不过如果⽬标字符串如下
>>> s='<usr1@mail1> usr2@maill2 <usr3@mail3 usr4@mail4> < usr5@mail5 '
⽽你想得到要么由⼀对 <> 包围起来的⼀个邮件地址,要么得到⼀个没有被 <> 包围起来的地址,但不想得到⼀对 <> 中间包围的多个地址或不完整的 <> 中的地址,那么使⽤这个式⼦并不能得到你想要的结果
>>> re.findall( r'(<)?/s*(/w+@/w+)/s*(?(1)>)' , s )
[('<', 'usr1@mail1'), ('', 'usr2@maill2'), ('', 'usr3@mail3'), ('', 'usr4@mail4'), ('', 'usr5@mail5')]
它仍然到了所有的邮件地址。
想要实现这个功能,单纯的使⽤ findall 有点吃⼒,需要使⽤其它的⼀些函数,⽐如 match 或 search 函数,再配合⼀些控制功能。这部分的内容将在下⾯详细讲解。
⼩结:以上基本上讲述了 Python 正则式的语法规则。虽然⼤部分语法规则看上去都很简单,可是稍不注意,仍然会得到与期望⼤相径庭的结果,所以要写好正则式,需要仔细的体会正则式规则的含义后不同规则之间细微的差别。
详细的了解了规则后,再配合后⾯就要介绍的功能函数,就能最⼤的发挥正则式的威⼒了。
re 模块的基本函数
在上⾯的说明中,我们已经对 re 模块的基本函数 ‘findall’ 很熟悉了。当然如果光有 findall 的话,很多功能是不能实现的。下⾯开始介绍⼀下 re 模块其它的常⽤基本函数。灵活搭配使⽤这些函数,才能充分发挥 Python 正则式的强⼤功能。查匹配的字符串函数
⾸先还是说下⽼熟⼈ findall 函数吧
findall(rule , target [,flag] )
在⽬标字符串中查符合规则的字符串。
第⼀个参数是规则,第⼆个参数是⽬标字符串,后⾯还可以跟⼀个规则选项(选项功能将在 compile 函数的说明中详细说明)。
返回结果结果是⼀个列表,中间存放的是符合规则的字符串。如果没有符合规则的字符串被到,就返回⼀个空列表。
2.1 使⽤ compile 加速
compile( rule [,flag] )
将正则规则编译成⼀个 Pattern 对象,以供接下来使⽤。
第⼀个参数是规则式,第⼆个参数是规则选项。
返回⼀个 Pattern 对象
直接使⽤ findall ( rule , target ) 的⽅式来匹配字符串,⼀次两次没什么,如果是多次使⽤的话,由于正
则引擎每次都要把规则解释⼀遍,⽽规则的解释⼜是相当费时间的,所以这样的效率就很低了。如果要多次使⽤同⼀规则来进⾏匹配的话,可以使例
>>> s='111,222,aaa,bbb,ccc333,444ddd'
>>> rule=r’/b/d+/b’
>>> compiled_rule=repile(rule)
>>> compiled_rule.findall(s)
['111', '222']
可见使⽤ compile 过的规则使⽤和未编译的使⽤很相似。 compile 函数还可以指定⼀些规则标志,来指定⼀些特殊选项。多个选项之间⽤ ’| ’ (位或)连接起来。
I IGNORECASE 忽略⼤⼩写区别。
L LOCAL 字符集本地化。这个功能是为了⽀持多语⾔版本的字符集使⽤环境的,⽐如在转义符/w ,在英⽂环境下,它代表[a-zA-Z0-9] ,即所以英⽂字符和数字。如果在⼀个法语环境下使⽤,缺省设置下,不能匹配 "é" 或 "ç" 。加上这 L 选项和就
M MULTILINE 多⾏匹配。在这个模式下 ’^’( 代表字符串开头 ) 和 ’$’( 代表字符串结尾 ) 将能够匹配多⾏的情况,成为⾏⾸和⾏尾标记。⽐如
>>> s=’123 456/n789 012/n345 678’
>>> rc=repile(r’^/d+’) # 匹配⼀个位于开头的数字,没有使⽤ M 选项
>>> rc.findall(s)
['123'] # 结果只能到位于第⼀个⾏⾸的 ’123’
>>> rcm=repile(r’^/d+’,re.M) # 使⽤ M 选项
>>> rcm.findall(s)
['123', '789', '345'] # 到了三个⾏⾸的数字
同样,对于 ’$’ 来说,没有使⽤ M 选项,它将匹配最后⼀个⾏尾的数字,即 ’678’ ,加上以后,就能匹配三个⾏尾的数字 456 012 和 678 了 .
>>> rc=repile(r’/d+$’)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论