• python正则表达式 - [学习]

    2008-09-18

    Tag:

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://chaoyueziwo21.blogbus.com/logs/29321087.html

    基本用法

    >>> 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',)

    随机文章:

    疑难杂症 2008-08-30

    收藏到:Del.icio.us