正则表达式

作者: blurryssky | 来源:发表于2016-05-17 15:18 被阅读329次

    本文来源,感谢分享
    http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html
    正则表达式当然不是python仅有,以下语法部分各语言适用,下文将针对python中re模块讲解适用方法

    语法

    语法 说明 表达式实体例 匹配的字符串
    一般字符 匹配自身 abc abc
    . 匹配任意除换行符"\n"外的字符, 在DOTALL模式中也能匹配换行符 a.c abc
    [...] "..."对应的位置可以是字符集中任意字符,可以逐个列出, 也可以给出范围,如[abc]或者[a-c]。第一个字符如果是^则表示取反,如[^abc]表示不是abc的其他字符 a[bcd]e abe ace ade
    \ 转义字符,如果有字符"."需要匹配,可以使用\.或者[.] a\.c a\\c a.c a\c
    \d 数字,相当于[0-9] a\dc a1c
    \D 非数字,相当于[^\d] a\Dc abc
    \s 空白字符,相当于[<blank>\t\r\n\f\v] a\sc a<blank>c
    \S 非空白字符,相当于[^\s] a\Sc abc
    \w 单词字符,相当于[A-Za-z0-9_] a\wc abc
    \W 非单词字符,相当于[^\w] a\Wc a<空格>c
    * 匹配前一个字符0次或者无限次 abc* ab abccc
    + 匹配前一个字符1次或者无限次 abc+ abc abccc
    ? 匹配前一个字符0次或者1次 abc? ab abc
    {m} 匹配前一个字符m次 ab{2}c abbc
    {m,n} 匹配前一个字符m至n次。m和n可以省略:若省略m,则匹配0至n次;若省略n,则匹配m至无限次 ab{1,2}c abc abbc
    ^ 匹配字符串开头,在多行模式中匹配每一行的开头 ^abc abc
    $ 匹配字符串末尾,在多行模式中匹配每一行的末尾 abc$ abc
    \A 仅匹配字符串开头 \Aabc abc
    \Z 仅匹配字符串末尾 abc\Z abc
    \b 匹配\w\W之间 a\b!bc a!bc
    \B 相当于[^\b] a\Bbc abc
    左右的表达式任意匹配一个,先尝试左边的表达式,成功则跳过右边的表达式,如果没有被包括在()中,则范围是整个表达式 abc⎢def abc def
    (...) "..."的内容将作为分组,从表达式左边开始每遇到一个(编号+1,后可接数量词 (abc){2} a(123⎢456)c abcabc a456c
    (?P<name>...) 分组,除了原有的编号再指定一个额外的别名 (?P<id>abc){2} abcabc
    <number> 引用编号为<number>的分组匹配到的字符串 (\d)abc\1 1abc1 5abc2
    (?P=name) 引用别名为<name>的分组匹配到的字符串 (?P<id>\d)abc(?P=id) 1abc1 5abc2
    (?:...) (...)的不分组版本,用于使用或后接数量词 (?:abc){2} abcabc
    (?iLmsux) iLmsux每个字符代表一个匹配模式,只能用在开头,可选多个 (?i)abc AbC
    (?#...) #后的内容将作为注释被忽略 abc(?#comment)123 abc123
    (?=...) =之后的字符串需要匹配表达式才能成功匹配 a(?=\d) a5
    (?!...) !之后的字符串内容需要不匹配表达式才能成功匹配 a(?!\d) as
    (?(id/name)yes-pattern⎢no-pattern) 如果编号为id或者别名为name的祖匹配到字符,则需要匹配yes-pattern,否则no-pattern (\d)abc(?(1)\d⎢abc) 1abc2 abcabc
    贪婪模式

    贪婪模式:总是尝试匹配尽可能多的字符,python默认模式
    非贪婪模式:总是尝试匹配尽可能少的字符
    若使用正则表达式ab*(非贪婪模式为ab*?),用于查找"abbbc",结果如下:
    贪婪:"abbb"(*尝试匹配了3次)
    非贪婪:"a"(*尝试匹配了0次)

    反斜杠的困扰

    大多数编程语言和正则表达式都使用""作为转义字符。假如需要匹配文中的字符"",那么使用编程语言表示的正则表达式将需要4个反斜杠"\\",先由编程语言翻译成"\",再由正则表达式翻译成""
    python中原生字符串应运而生,"\\"可以使用r"\"来表示(python将不对其进行反斜杠转义,而正则中仍需要转义),"\d"可写成r"\d"

    re模块

    通常的使用步骤

    首先创建pattern对象,再使用pattern对象的实例方法

    import re
    pattern = re.compile(r'hello')
    match = pattern.match('hello world!')
    if match:
        print match.group()
    ### 输出 ### 
    #hello
    

    也可以使用模块方法用于完成正则表达式的功能,上面的例子可以简写为:

    match = re.match(r'hello', 'hello world!')
    if match:
        print match.group()
    ### 输出 ### 
    #hello
    
    re.compile(strPattern[, flag])方法

    第一个参数为字符串
    第二个参数flag是匹配模式,可省略
    可选值有:

    • re.I: 忽略大小写
    • re.M: 多行模式,改变^$的行为
    • re.S: 点任意匹配模式,改变.的行为
    • re.L: 使预定字符类\w \W \b \B \s \S取决于当前区域设定
    • re.U: 使预定字符类\w \W \b \B \s \S \d \D取决于unicode定义的字符属性
    • re.X: 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。以下两个正则表达式是等价的:
    a = re.compile(r"""\d +  # the integral part
                            \.    # the decimal point
                            \d *  # some fractional digits""", re.X)
    b = re.compile(r"\d+\.\d*")
    

    取值可以使用按位或运算符|表示同时生效,比如re.I | re.M
    也可以在regex字符串中指定模式,比如re.compile('pattern', re.I | re.M)re.compile('(?im)pattern')是等价的。


    Pattern

    Pattern对象是一个编译好的正则表达式,通过Pattern提供的一系列方法可以对文本进行匹配查找
    Pattern不能直接实例化,必须使用re.compile()进行构造
    Pattern提供了几个可读属性用于获取表达式的相关信息:

    • pattern: 编译时用的表达式字符串。
    • flags: 编译时用的匹配模式。数字形式。
    • groups: 表达式中分组的数量。
    • groupindex: 以表达式中有别名的组的别名为键、以该组对应的编号为值的字典,没有别名的组不包含在内。
    import re
    p = re.compile(r'(\w+)(\w+)(?P<sign>.*)', re.DOTALL)
     
    print "p.pattern:", p.pattern
    print "p.flags:", p.flags
    print "p.groups:", p.groups
    print "p.groupindex:", p.groupindex
     
    ### 输出 ### 
    # p.pattern: (\w+)(\w+)(?P<sign>.*)
    # p.flags: 16
    # p.groups: 3
    # p.groupindex: {'sign': 3}
    
    match(),字符串开始部分相同即可成功
    实例方法 模块方法
    match(string[, pos[, endpos]]) re.match(pattern, string[, flags])
    • match()将从string的pos下标处起尝试匹配pattern,如果pattern结束时仍可匹配,则返回一个Match对象;
    • 如果匹配过程中pattern无法匹配,或者匹配未结束就已到达endpos,则返回None。
    • pos和endpos的默认值分别为0和len(string)
    • 模块方法re.match()无法指定这两个参数,参数flags用于编译pattern时指定匹配模式。
    • 当pattern结束时若string还有剩余字符,仍然视为成功。想要完全匹配,可以在表达式末尾加上边界匹配符$
    search(),字符串中存在相同即可成功
    实例方法 模块方法
    search(string[, pos[, endpos]]) re.search(pattern, string[, flags])
    • 从string的pos下标处起尝试匹配pattern,如果pattern结束时仍可匹配,则返回一个Match对象
    • 若无法匹配,则将pos加1后重新尝试匹配,直到pos=endpos时仍无法匹配则返回None。
    • pos和endpos的默认值分别为0和len(string))
    • re.search()无法指定这两个参数,参数flags用于编译pattern时指定匹配模式。
    import re
    pattern = re.compile(r'world') 
    match = pattern.search('hello world!') 
    if match:
            print match.group() 
    ### 输出 ### 
    # world
    
    spilt()
    实例方法 模块方法
    split(string[, maxsplit]) re.split(pattern, string[, maxsplit])
    • 按照能够匹配的子串将string分割后返回列表
    • maxsplit用于指定最大分割次数,不指定将全部分割。
    import re 
    p = re.compile(r'\d+')
    print p.split('one1two2three3four4') 
    ### output ###
    # ['one', 'two', 'three', 'four', '']
    
    findall()
    实例方法 模块方法
    findall(string[, pos[, endpos]]) re.findall(pattern, string[, flags])
    • 搜索string,以列表形式返回全部能匹配的子串。
    import re 
    p = re.compile(r'\d+')
    print p.findall('one1two2three3four4') 
    ### output ###
    # ['1', '2', '3', '4']
    
    finditer()
    实例方法 模块方法
    finditer(string[, pos[, endpos]]) re.finditer(pattern, string[, flags])
    • 搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。
    import re 
    p = re.compile(r'\d+')
    for m in p.finditer('one1two2three3four4'):
        print m.group()
    ### output ###
    # 1 2 3 4
    
    sub()
    实例方法 模块方法
    sub(repl, string[, count]) re.sub(pattern, repl, string[, count])
    • 使用repl替换string中每一个匹配的子串后,返回替换后的字符串
    • 当repl是一个字符串时,可以使用\id或\g<id>、\g<name>引用分组,但不能使用编号0
    • 当repl是一个方法时,这个方法应当只接受一个参数(Match对象),并返回一个字符串用于替换(返回的字符串中不能再引用分组)。
    • count用于指定最多替换次数,不指定时全部替换。
    import re 
    p = re.compile(r'(\w+) (\w+)')
    s = 'i say, hello world!' 
    print p.sub(r'\2 \1', s) 
    ### output ###
    # say i, world hello!
    
    subn()
    实例方法 模块方法
    subn(repl, string[, count]) re.sub(pattern, repl, string[, count])
    • 返回 (sub(repl, string[, count]), 替换次数)。
    import re 
    p = re.compile(r'(\w+) (\w+)')
    s = 'i say, hello world!' 
    print p.subn(r'\2 \1', s)
    ### output ###
    # ('say i, world hello!', 2)
    

    Match

    Match对象是一次匹配的结果,包含了很多关于此次匹配的信息,可以使用Match提供的可读属性方法来获取这些信息

    属性:

    • string: 匹配时使用的文本
    • re: 匹配时使用的Pattern对象
    • pos: 文本中正则表达式开始搜索的索引
    • endpos: 文本中正则表达式结束搜索的索引
    • lastindex: 最后一个被捕获的分组在文本中的索引
    • lastgroup*: 最后一个被捕获的分组的别名

    方法:

    • group([group1, …]):
    • 获得一个或多个分组截获的字符串,指定多个参数时将以元组形式返回
    • group1可以使用编号也可以使用别名
    • 编号0代表整个匹配的子串;不填写参数时,返回group(0)
    • 没有截获字符串的组返回None;截获了多次的组返回最后一次截获的子串
    • groups([default]):
    • 以元组形式返回全部分组截获的字符串
    • 相当于调用group(1,2,…last)
    • default表示没有截获字符串的组以这个值替代,默认为None。
    • groupdict([default]):
    • 返回以有别名的组的别名为键、以该组截获的子串为值的字典,没有别名的组不包含在内
    • default含义同上。
    • start([group]):
    • 返回指定的组截获的子串在string中的起始索引(子串第一个字符的索引)
    • group默认值为0
    • end([group]):
    • 返回指定的组截获的子串在string中的结束索引(子串最后一个字符的索引+1)
    • group默认值为0
    • span([group]): 返回(start(group), end(group))
    • expand(template):
    • 将匹配到的分组代入template中然后返回
    • template中可以使用\id或\g<id>、\g<name>引用分组,但不能使用编号0
    • \id与\g<id>是等价的,但\10将被认为是第10个分组,如果你想表达\1之后是字符'0',只能使用\g<1>0。
    import re
    m = re.match(r'(\w+) (\w+)(?P<sign>.*)', 'hello world!')
     
    print "m.string:", m.string
    print "m.re:", m.re
    print "m.pos:", m.pos
    print "m.endpos:", m.endpos
    print "m.lastindex:", m.lastindex
    print "m.lastgroup:", m.lastgroup
     
    print "m.group(1,2):", m.group(1, 2)
    print "m.groups():", m.groups()
    print "m.groupdict():", m.groupdict()
    print "m.start(2):", m.start(2)
    print "m.end(2):", m.end(2)
    print "m.span(2):", m.span(2)
    print r"m.expand(r'\2 \1\3'):", m.expand(r'\2 \1\3')
     
    ### output ###
    # m.string: hello world!
    # m.re: <_sre.SRE_Pattern object at 0x016E1A38>
    # m.pos: 0
    # m.endpos: 12
    # m.lastindex: 3
    # m.lastgroup: sign
    # m.group(1,2): ('hello', 'world')
    # m.groups(): ('hello', 'world', '!')
    # m.groupdict(): {'sign': '!'}
    # m.start(2): 6
    # m.end(2): 11
    # m.span(2): (6, 11)
    # m.expand(r'\2 \1\3'): world hello!
    

    相关文章

      网友评论

        本文标题:正则表达式

        本文链接:https://www.haomeiwen.com/subject/vvkirttx.html