zoukankan      html  css  js  c++  java
  • python3 正则匹配[^abc]和(?!abc)的区别(把多个字符作为一个整体匹配排除)

    目的:把数字后面不为abc的字符串找出来

    如1ab符合要求,2abc不符合要求

     1 str = '1ab'
     2 out = re.match(r'd+(?!abc)',str)
     3 
     4 str1 = '1abc'
     5 out1 = re.match(r'd+(?!abc)',str1)
     6 
     7 print('out:',out)
     8 print('out1:',out1)
     9 #
    10 #out: <_sre.SRE_Match object; span=(0, 1), match='1'>
    11 #out1: None
    12 #

    如果把(?!abc)改为[^abc],效果如下:

     1 str = '1ab'
     2 out3 = re.match(r'd+[^abc]',str)
     3 
     4 str1 = '1abc'
     5 out4 = re.match(r'd+[^abc]',str1)
     6 
     7 print('out:',out3)
     8 print('out1:',out4)
     9 
    10 #
    11 #out3: None
    12 #out4: None

     总结:

    (?!abc)是把abc当做一个整体进行匹配,字符串中不存在abc才能成功,abc作为一个整体进行匹配

    [^abc]只要字符串中存在a/b/c中的任一个即匹配不成功,字符串中不能出现a/b/c中的任一个

    ------------------------------------------------------------------

    更新:

    之前没有注意到(?!abc)方式匹配字符串不消耗字符串内容这句话,导致如果字符串中间排除一个子字符串时会出现错误。

    更新关于这部分的理解

    (?=...)  # 匹配字符串,且紧挨着匹配的字符串之后的字符等于...,才算匹配成功,且不消耗字符串内容

    (?!...)  # 匹配字符串,且紧挨着匹配的字符串之后的字符不等于...,才算匹配成功,且不消耗字符串内容

    (?<=...) # 匹配字符串,且紧挨着匹配的字符串之前的字符等于...,才算匹配成功,且不消耗字符串内容

    (?<!...) # 匹配字符串,且紧挨着匹配的字符串之前的字符不等于...,才算匹配成功,且不消耗字符串内容

    具体理解:

    (?=...)为例

    1 reg = re.compile('A(?=BC)')
    2 reg.search('ABC')
    3 reg.search('ABCDE')
    4  
    5  
    6 # 输出:
    7 # <_sre.SRE_Match object; span=(0, 1), match='A'>
    8 # <_sre.SRE_Match object; span=(0, 1), match='A'>
    1 reg_1 = re.compile('A(?=BC)D')
    2 print(reg_1.search('ABCD'))
    3 
    4 
    5 # 输出
    6 # None

      reg = re.compile('A(?=BC)')

         reg.search('ABC')

      在这种情况下,匹配一个字符,这个字符包含'A',且'A'后面的字符为'BC',字符串'ABCD'符合规律

     但是,

    reg_1 = re.compile('A(?=BC)D')
    reg_1.search('ABCD')

    就会出现问题,因为(?=...)括号内的表达式不消耗字符,也就是说匹配完字符串中的'A'之后,会判断A之后的字符是否是'BC',匹配成功后正则表达式会继续匹配字符串中'A'之后的字符是否是'D'
    但是,在字符串中'A'之后是'B'就会出现匹配失败,返回None.
    https://blog.csdn.net/lxcnn/article/details/4304651 在这个链接中,解释比较清楚.
    在正则匹配过程中,各个子表达式会依次取得控制权,对字符串进行匹配.
    比如例子中的
    reg_1 = re.compile('A(?=BC)D')
    1.'A(?=BC)D' 中,表达式'A'首先取得控制权,从字符串'ABCD'的开始位置('A'之前)进行匹配;
      匹配成功,控制权交给下一个正则子表达式(?=BC),匹配位置移动到字符串'ABCD'中的'A'之后('B'之前)
    2.正则子表达式(?=BC)取得控制权,对当前匹配位置的右侧字符进行匹配,判断是否等于(?=BC)中的'BC'(即'A'后的'BC');
      匹配成功,控制权交给下一个正则子表达式'D',但是,因为(?=...)表达式不消耗字符,也就是说这个表达式是零宽度的,因此匹配位置不会往后移动.匹配位置依然在'A'之后.
    3.正则子表达式'D'取得控制权,对当前位置('A'之后'B'之前)的右侧字符进行匹配,判断'A'之后的字符是否等于'D'.
      字符串'ABCD'中,'A'之后为'B',匹配失败
    4.进行下一轮匹配,又回到表达式'A'取得控制权,开始匹配位置不再是字符串首位置,此时从字符串'ABCD'中的'A'之后'B'之前的位置开始匹配,重复1~3步骤,不断移动匹配位置进匹配

    整个正则表达式匹配过程明了了.

    不消耗字符串的意思就是这个子表达式为零宽度的,在匹配结束后不会向后移动匹配位置
    
    
     


     

  • 相关阅读:
    三大高级排序
    三大初级排序算法
    MVC的JsonResult用法
    使用dynamic类型改进反射
    正则指引-括号(3)反向引用
    正则指引-括号(2)引用分组
    正则指引-括号(1)
    正则指引-量词demo
    正则指引-字符组demo
    ASP.NET MVC 分部视图
  • 原文地址:https://www.cnblogs.com/congyinew/p/7473835.html
Copyright © 2011-2022 走看看