• 预搜索经典案例分析


    C# code
    string str ="aaa bbbb ffffff 999999999"; Regex r = new Regex(@"(\w)((?=\1\1\1)(\1))+"); foreach (Match m in r.Matches(str)) { Console.WriteLine("Match:Value={0},Index={1},Length={2}", m.Value, m.Index, m.Length); }


    结果如下:
    Match:Value=bb,Index=4,Length=2
    Match:Value=ffff,Index=9,Length=4
    Match:Value=9999999,Index=16,Length=7

    表达式 "(\w)((?=\1\1\1)(\1))+" 在匹配字符串 "aaa ffffff 999999999" 时,将可以匹配4个"b"的前2个,可以匹配6个"f"的前4个,可以匹配9个"9"的前7个。我想问的是为什么漏掉的总是最后两个字母?它们为什么不能匹配成功?哪个规则导致了这种影响?能详细说说好吗?

    (\w)          # 匹配一个单词字符
    (             # 分组开始
      (?=\1\1\1)  # 紧接着必须是三个和前面的一样的字符,但不吃进字符
      (\
    1)        # 匹配一个和前面一样的字符
    )
    +# 匹配一个或多个这样的分组


    楼主的正则,(\w)((?=\1\1\1)(\1))+,其实就等价于
    (\w)(\1)*(?=\1\1\1)(\1)

    这个会相对好理解一些

    说下分析过程,因为+表示{1,},下面的“次数”表示((?=\1\1\1)(\1))+匹配成功的次数
    次数 楼主的正则等价于
    1 (\w)((?=\1\1\1)(\1))
    2 (\w)((?=\1\1\1)(\1))((?=\1\1\1)(\1))
    3 (\w)((?=\1\1\1)(\1))((?=\1\1\1)(\1))((?=\1\1\1)(\1))
    ...

    因为如果最后一个((?=\1\1\1)(\1))匹配成功,那么中间的((?=\1\1\1)(\1))一定成功,所以中间的限制条件(?=\1\1\1)就没有意义了,这时就可以简写为(\1)
    也就是
    次数 楼主的正则等价于
    1 (\w)((?=\1\1\1)(\1))
    2 (\w)(\1)((?=\1\1\1)(\1))
    3 (\w)(\1)(\1)((?=\1\1\1)(\1))
    ...

    可以归纳为等价于
    (\w)(\1)*((?=\1\1\1)(\1))
    因为((?=\1\1\1)(\1))开始和结尾的()原来是用作量词+限制范围的,这里已经没有什么意义了,所以表达式最后可以归纳为等价于
    (\w)(\1)*(?=\1\1\1)(\1)

    分析这个表达式就容易多了
    (\w)匹配一个字符,占一位,\1是对\w匹配内容的引用,(\1)*可以匹配0到无穷多个(\w)匹配到的字符,(?=\1\1\1)(\1)只占一位,但是(?=\1\1\1)要求所在位置右侧有三个(\w)匹配到的字符,所以在(?=\1\1\1)这个位置右侧应该有三个字符,只是最后两个不计入最后的匹配结果

    以999999999为例,第一个9由(\w)匹配,第二到第六个9由(\1)来匹配,第七个9由(?=\1\1\1)(\1)中最后的(\1)来匹配,而第七、八、九这三个9是用来保证满足(?=\1\1\1)这个条件的

  • 相关阅读:
    Oracle11g新建用户及用户表空间
    PLSQL连接oracle12c
    Zabbix微信报警脚本及写触发记录
    使用document.select(Jquery Css selector) selector:看jsoup文档来敲案例学习 selector选择器
    仙女打卡day1
    XML的解析(读取),附带源码与运行效果图 (day01)
    [Luogu] P7077 函数调用
    [Luogu] P5815 [CQOI2010]扑克牌
    [Luogu] CF364D Ghd
    [Luogu] P4823 [TJOI2013]拯救小矮人
  • 原文地址:https://www.cnblogs.com/AndyGe/p/2426925.html
Copyright © 2020-2023  润新知