博客首页 注册 建议与交流 排行榜 加入友情链接
推荐 投诉 搜索: 帮助

IMA -- 纸条箱

ima.cublog.cn


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"之类的,
会被自动替换,有两种方法保持原义:

  1. 转义符号表示 "abc\n" 表示为 "abc\\n"
  2. 用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',)






发表于: 2007-04-01 ,修改于: 2007-05-25 01:27,已浏览1077次,有评论0条 推荐 投诉


网友评论

发表评论