ima
- UID
- 40665
- 帖子
- 65
- 积分
- 149
- 在线时间
- 6 小时
|
1#
ima 发表于 2007-04-01 23:11
python正则表达式学习笔记
原文参见
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\g依此引用顺序定义的分组
对不不会引用的分组用?:...表示,如(?:abc)表示(abc)被忽略
可以用?P方式定义一个命名的分组 (?P[1-9][1-9]?)定义了分组名子为"id"\
对命名的分组,可以用编号的方法引用:\k;也可以用\g方式引用,还可以用?P=name引用
msg="03/06/2007"
pattern = r"(?P\d+)/(?P\d+)/(\d+)"
myre = re.compile(pattern)
trans = r"\3年\g月\g日"
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:
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',)
|