美文网首页
正则表达式的基本使用 2018-07-30

正则表达式的基本使用 2018-07-30

作者: 陈zhih | 来源:发表于2018-07-31 00:58 被阅读0次

    正则表达式是编程过程中进行字符串模式识别、字符串处理的强力工具。学过一些自动机理论就知道正则表达式其实是有穷自动机,其可以识别的字符串集合称为其语言。正则表达式使用的是一种线性的、非递归的文法,并提供有限的上下文有关文法。

    符号

    1. 字面值表达式

    就是普通的,没有带任何标记的字符串

    text = r'this is a sample text'
    
    print(re.findall(r'is a',text))
    for i in re.finditer(r'is a',text):
        print(i.group(),i.start())
    
    <<< ['is a']
    <<< is a 5
    
    1. 或表达式 re1|re2

    用于匹配两个正则语言的并集
    下面例子使用'-' 或 '|'来分割字符串

    text = r'123/123-4212-4242/23543'
    
    for item in re.split(r'(?:/|-)',text):
        print(item)
    
    <<< 123
    <<< 123
    <<< 4212
    <<< 4242
    <<< 23543
    
    1. . 匹配任何字符(除了\n 之外)
    text = r'123/123-42abc12-4242/23543'
    print(re.findall(r'-.......-',text))
    
    <<< ['-42abc12-']
    
    1. ^ 匹配字符串起始部分
    text = r'123qwe123'
    
    for it in re.finditer(r'^123',text):
        print(it.start())
    
    <<< 0
    
    1. $ 匹配字符串终止部分
    
    text = r'123qwe123'
    
    for it in re.finditer(r'123$',text):
        print(it.start())
    
    <<< 6
    
    1. * 匹配 0 次或者多次前面出现的正则表达式
    text = r'''\
    Cool     Things
    Cool Things
    CoolThings
    '''
    print(re.findall(r'\w\w\w\w\s*\w\w\w\w\w\w',text))
    
    <<< ['Cool     Things', 'Cool Things', 'CoolThings']
    

    Cool 和 Things,之间可以有一个或多个空格,或者没有

    1. + 匹配 1 次或者多次前面出现的正则表达式
    text = r'''\
    Cool     Things
    Cool Things
    CoolThings
    '''
    print(re.findall(r'\w\w\w\w\s+\w\w\w\w\w\w',text))
    
    <<< ['Cool     Things', 'Cool Things']
    

    Cool 和 Things,之间可以有一个或多个空格

    1. ? 匹配 0 次或者 1 次前面出现的正则表达式
    text = r'''\
    Cool     Things
    Cool Things
    CoolThings
    '''
    print(re.findall(r'\w\w\w\w\s?\w\w\w\w\w\w',text))
    
    <<< ['Cool Things', 'CoolThings']
    

    Cool 和 Things,之间可以有一个空格,或者没有

    1. {N}匹配 N 次前面出现的正则表达式

    将前面的大量重复改善

    text = r'''\
    Cool     Things
    Cool Things
    CoolThings
    '''
    print(re.findall(r'\w{4}\s*\w{6}',text))
    
    <<< ['Cool     Things', 'Cool Things', 'CoolThings']
    
    1. {M,N} 匹配 M~N 次前面出现的正则表达式
    text = '''\
    www.baidu.com
    www.google.com
    www.360.com
    www.errorformat
    '''
    
    for it in re.finditer(r'www(\.\w+){2,3}',text):
        print(it.group())
    
    <<< www.baidu.com
    <<< www.google.com
    <<< www.360.com
    
    1. […] 匹配来自字符集的任意单一字符

    找出元音字母的位置

    
    text = '''\
    I believe, for every drop of rain
    that falls, A flower grows...
    I believe that somewhere in the
    darkest night, A candle glows...
    '''
    
    for it in re.finditer(r'(?i)[aeiou]',text):
        print(it.start(),end=' ')
    
    <<< 0 3 5 6 8 12 15 17 23 26 30 31 36 40 46 50 52 57 64 67 69 70 72 76 80 82 85 87 89 94 97 100 105 111 114 118 122
    
    1. [..x−y..] 匹配 x ~ y 范围中的任意单一字符

    找出一串中能形成8进制数的字符串

    text = '''\
    adas a1290 21469
    12412 762 10923
    aeqw
    '''
    
    for it in re.finditer(r'\b[0-7]+\b',text):
        print(it.group(),end=' ')
    
    <<< 12412 762
    
    1. [^…] 不匹配此字符集中出现的任何一个字符,包括某一范围的字符(如果在此字符集中出现)

    找出不含数字的非空白单词

    text = '''\
    adas a1290 21469
    12412 762 10923
    aeqw
    '''
    print(repr(text))
    for it in re.finditer(r'\b[^0-9\s]+\b',text):
        print(it.group(),end=' ')
    
    <<< adas aeqw
    
    1. (…) 匹配封闭的正则表达式,然后另存为子组

    有一点组合设计模式的味道,() 内也是完整的正则表达式,可以用于提取子组

    text = '''\
    11/27/1997
    5/22/1998
    2/29/1996
    '''
    
    print(repr(text))
    for it in re.finditer(r'(\d+)/(\d+)/(\d+)',text):
        print(it.group(3),'年',it.group(1),'月',it.group(2),'日')
    
    <<< 1997 年 11 月 27 日
    <<< 1998 年 5 月 22 日
    <<< 1996 年 2 月 29 日
    
    1. (*|+|?|{})? 用于匹配上面频繁出现/重复出现符号的非贪婪版本 (*、+、?、{})

    其行为与贪婪相反,贪婪匹配会尽可能多的匹配字符,回溯的时候再减少匹配的字符。
    非贪婪匹配会尽可能少的匹配,回溯的时候再增加匹配的字符。

    text = '''\
    3.1415926
    3.14
    '''
    
    print(repr(text))
    for it in re.finditer(r'\d+\.[\d]{4,6}?',text):
        print(it.group())
    
    <<< 3.1415
    

    特殊字符

    前面出现了很多形如 \w \b \d 的特殊符号,下面总结:

    1. \d 匹配任何十进制数字,与[0-9]一致(\D\d 相反,不匹配任何非数值型的数字)

      如: data\d+.txt匹配 data1.txt 、data2.txt ……

    2. \w 匹配任何字母数字字符,与[A-Za-z0-9_]相同(\W 与之相反)

      如: 标识符表示为 [a-zA-Z_]\w+

    3. \s 匹配任何空格字符,与[\n\t\r\v\f]相同(\S 与之相反)

      如: You\sare\sthe\winner

    4. \b 匹配任何单词边界(\B 与之相反)

      如: \bThe\b

    5. \N 匹配已保存的子组 N(参见上面的(…))

    匹配第二个数字以第一个数字为前缀的字符串

    text = '''\
    3.14  3.1415926 
    '''
    
    m = re.match(r'(\d+\.\d+)\s+(\1\d+)',text)
    if m is not None:
        print(m.group(1),m.group(2))
    
    <<< 3.14 3.1415926
    
    1. \c 逐字匹配任何特殊字符 c(即,仅按照字面意义匹配,不匹配特殊含义)

      c 包括 . \ ' [ ] { } ( ) ? + * 等用于正则表达式的标记符号

    2. \A(\Z) 匹配字符串的起始(结束)(另见上面介绍的^$

      如: \ADear

    扩展正则表达式

    1. (?iLmsux) 在正则表达式中嵌入一个或者多个特殊“标记”参数(或者通过函数/方法)

      1. 使用时(?...)是一体的,置于正则表达式的最左端
      2. (?i) 用于忽略大小写,如前所示的元音字母就使用了r'(?i)[aeiou]'
      3. (?m) 实现跨行搜索,而不是将字符串看做整体,可以使 ^& 匹配每一行的首尾
      4. (?s) 使得 . 可以匹配换行符\n
      5. (?x) 该标记允许用户通过抑制在正则表达式中使用空白符(除了在字符类中或者在反斜线转义中)来创建更易读的正则表达式。
    2. (?:…) 表示一个匹配不用保存的分组

      使用该标记后,分组将不会被保存到matchObj.groups()中

    3. (?P<name>…) 像一个仅由 name 标识而不是数字 ID 标识的正则分组匹配

      该标记可以给分组起名字

    4. (?P=name) 在同一字符串中匹配由(?P=name)分组的之前文本

    改写之前的例子

    text = '''\
    3.14  3.1415926 
    '''
    
    m = re.match(r'(?P<prefix>\d+\.\d+)\s+((?P=prefix)\d+)',text)
    if m is not None:
        print(m.group(1),m.group(2))
    
    <<< 3.14 3.1415926
    

    sub方法中可以用g<name>来检索分组名

    text = '''\
    11/27/1997\
    '''
    
    res = re.sub(r'(?P<mon>\d+)/(?P<day>\d+)/(?P<year>\d+)',r'\g<day>/\g<mon>/\g<year>',text)
    print(res)
    
    <<< 27/11/1997
    
    1. (?#…) 表示注释,所有内容都被忽略

    2. (?=…) 匹配条件是如果…出现在之后的位置,而不使用输入字符串;称作正向前视断言

    意思是匹配的时候向前尝试匹配后缀,如果后缀匹配成功,则匹配前缀

    text = '''\
    11/27/1997\
    '''
    
    for it in re.finditer(r'\d{1,2}/\d{1,2}(?=/\d{4})',text):
        print(it.group())
    
    <<< 11/27
    
    1. (?!…) 匹配条件是如果…不出现在之后的位置,而不使用输入字符串;称作负向前视断言

    (?=…) 相反,如果后缀不能匹配,这匹配前缀

    1. (?<=…) 匹配条件是如果…出现在之前的位置,而不使用输入字符串;称作正向后视断言

    检查前缀,如果前缀匹配,则匹配后缀

    text = '''\
    ABC12345 qd7654\
    '''
    print(text)
    print()
    for it in re.finditer(r'(?<=[a-zA-Z]{3})\d+',text):
        print(it.group())
    
    <<< 12345
    
    1. (?<!…) 匹配条件是如果…不出现在之前的位置,而不使用输入字符串;称作负向后视断言

    检查前缀,如果前缀不匹配,则匹配后缀

    1. (?(id/name)Y|N ) 如果分组所提供的 id 或者 name(名称)存在,就返回正则表达式的条件匹配 Y,如果不存在,就返回 N|N是可选项

    相关文章

      网友评论

          本文标题:正则表达式的基本使用 2018-07-30

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