原文参见 http://wiki.ubuntu.org.cn/Python%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%93%8D%E4%BD%9C%E6%8C%87%E5%8D%97
本文介绍适用于python 1.5版本(包括)以上的re模块
基本用法
>>> import re >>> p=re.compile("word ") >>> m=p.search("abcwords secondword third") >>> dir(m) ['__copy__', '__deepcopy__', 'end', 'expand', 'group', 'groupdict', 'groups', 'span', 'start'] >>> m.span() (15, 20) >>> dir(p) ['__copy__', '__deepcopy__', 'findall', 'finditer', 'match', 'scanner', 'search', 'split', 'sub', 'subn'] >>> dir(re) ['DOTALL', 'I', 'IGNORECASE', 'L', 'LOCALE', 'M', 'MULTILINE', 'S', 'U', 'UNICODE', 'VERBOSE', 'X', '__all__', '__builtins__', '__doc__', '__file__', '__name__', 'compile', 'engine', 'error', 'escape', 'findall', 'finditer', 'match', 'purge', 'search', 'split', 'sub', 'subn', 'template']
|
python的元字符
基本和一般的正则表达式定义一样 "["和"]" 指定一个字符集合,可以枚举,也可以用"-"表示范围 如[3-6]:表示数字3,4,5,6的任意一个 [a-z]:表示所有小写字符 部分元字符在[]中失去特殊含义 "." 匹配除换行符以外的任意一个字符,re.DOTALL模式下例外 "*" 表示任意个重复出现 "+" 表示至少一个出现 "?" 表示至多出现一次 "{}" 表示出现的次数范围 {1,10},{,2},{3,} "^"和"$" 分别表示开始和结尾 "|" 逻辑或 "()" 分组 "\" 转意符号,可将元字符表示为一般的字符 \$ ,\\,\( 常用的转意集合 \d [0-9] \D [^0-9] \s 任何空白字符;它相当于类 [ \t\n\r\f\v] \S [^\s] \w [a-zA-Z0-9_] \W [^\w] \A 字符串首 \Z 字符串尾 \b 单词边界 [^a-zA-Z0-9] \B 非单词边界 "\Babc" 匹配"sd abcdabc"第二个 "abc"
表示方法
正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行.
初始化时,正则表达式被当做python风格的字符串传入,如果有"\b""\t"之类的, 会被自动替换,有两种方法保持原义:
- 转义符号表示 "abc\n" 表示为 "abc\\n"
- 用raw格式字符串 r'abc\n'
基本使用
编译模式
使用一个变量保存初始化结果,初始化将完成编译过程 然后可以多次使用,如示例中所示
模块级函数编译后立刻使用,系统会缓存编译结果
>>> re.search("word ","abcwords secondword third").span() (15, 20)
| 前者可以在运行时节省编译时间
方法说明
编译对象方法
>>> p=re.compile(r'^[12][0-9]{1,2}') >>> dir(p) ['__copy__', '__deepcopy__', 'findall', 'finditer', 'match', 'scanner', 'search', 'split', 'sub', 'subn']
|
match 从输入串的开始比较,看是否匹配,返回一个匹配对象或者None
search 全文匹配,返回匹配对象或者None
split 按照匹配的串将字符串分成子串,返回列表,可以控制子串数目
sub 将匹配的串替换成指定的串
subn 多返回替换次数
findall 返回所由匹配的首坐标
finditer 返回匹配的迭代器
>>> m=p.search("234abcd") >>> dir(m) ['__copy__', '__deepcopy__', 'end', 'expand', 'group', 'groupdict', 'groups', 'span', 'start']
|
匹配对象方法span 匹配的首末坐标元组 group 匹配的组
编译标志re.compile(reg,flag)
|
标志及缩写
|
含义 |
|
DOTALL, S |
使 . 匹配包括换行在内的所有字符 |
|
IGNORECASE, I |
使匹配对大小写不敏感 |
|
LOCALE, L |
做本地化识别(locale-aware)匹配 |
|
MULTILINE, M |
多行匹配,影响 ^ 和 $ |
|
VERBOSE, X |
能够使用 REs 的 verbose 状态,使之被组织得更清晰易懂 |
高级使用
分组将一个串作为一个整体表示 r'(abc)*'匹配任意个abc的连续出现 分组可以欠套,和vi的相似 可以用\1,\2,...或者\g<1>\g<2>依此引用顺序定义的分组 对不不会引用的分组用?:...表示,如(?:abc)表示(abc)被忽略 可以用?P<name>方式定义一个命名的分组 (?P<id>[1-9][1-9]?)定义了分组名子为"id"\ 对命名的分组,可以用编号的方法引用:\k;也可以用\g<name>方式引用,还可以用?P=name引用
msg="03/06/2007" pattern = r"(?P<mouth>\d+)/(?P<day>\d+)/(\d+)" myre = re.compile(pattern) trans = r"\3年\g<mouth>月\g<2>日" ret = myre.sub(trans,msg) print ret 2007年03月06日 def trans(reg): tu = reg.groups() return "%s年%S月%s日"%(tu[2],tu[0].lstrip("0"),tu[1].lstrip("0"))#groups里面仍旧按照匹配的顺序排列 ret = myre.sub(trans,msg) 2007年3月6日 |
|
肯定定界符?=...
否定定界符?!... 匹配非的情况 .*[.](?!bat$|exe$).*$
匹配与替换"*"匹配默认是贪婪算法,接合?可以改为非贪婪算法,如*?,对于+,?,{m,n}的情况,需要实验确认是否是默认贪婪算法 reg.sub(替换模型,原型[,替换次数]) 替换模型是一个原模式串的函数,可以是常量.接合分组标记,可以实现复杂的串转换 工作原理如下:替换模型对象依此接收到从原型里面匹配到的匹配对象(reg.REG_Match 类型),然后根据该类型返回相应的替换串;re 将替换原型返回的串代替匹配到的串,继续下一次匹配. 替换模型 非常灵活,例如
count = 0 def trans(reg): global count count = count + 1 print type(reg) return "This is %s[%s] "%(count,reg.group())
myre = re.compile(r"(?=\W?)http://(?:www\.)?\w+(?:\w+\.){0,2}\.com/")
urls="Please see Google's Terms of Service posted at http://www.google.com/terms_of_service.html" res = myre.sub(trans,urls) out:<type '_sre.SRE_Match'> print res out:Please see Google's Terms of Service posted atThis is 5[http://www.google.com/] terms_of_service.html
|
findall() 返回列表,如果一次匹配中有有名分组,则列表的项成为分组组成的元组
注意事项
不要杀鸡用牛刀,跟据具体问题选用合适的工具. 一般越特化的处理方式效率越高. 参考string.replace string.join,string.split方法
1 >>> m = re.match("([abc])+", "abc") 2 >>> m.groups() 3 ('c',)
|
|