可变宽度消极后视明星与加数量词

问题描述:

愚蠢的问题在这里...我试图匹配线内的空白,而忽略了领先的空格/标签,想出了这些正则表达式字符串,但我想不出为什么只有一个在工作(C#正则表达式引擎):可变宽度消极后视明星与加数量词

(?<!^[ \t]*)[ \t]+  // regex 1. (with *) 
(?<!^[ \t]+)[ \t]+  // regex 2. (with +) 

注意明星重复在负前瞻。当符合这些反对" word1 word2"(2前导空格):

⎵⎵word1⎵word2    
    ^    // 1 match for regex 1. (*) 

⎵⎵word1⎵word2    
^^ ^    // 2 matches for regex 2. (+) 
^ ^    // why not match like this? 

为什么只版本1(星)在这里工作和版本2(加)无法比拟的第二大空间?

我认为这是因为贪婪+[ \t]+的优先级高于预先的优先级,但我该如何合理化以期待这一点?

+1

这实际上很容易理解。负向lookbehind只是检查当前位置是否没有以lookbehind模式开头。因此,'+'版本将匹配最初的空白字符串,因为字符串的开头不会以字符串的开头和至少1个空白字符开头。 –

+0

所以基本上这个引擎:1.把第一个字符(第一个空格)重复长度为1; 2.再次应用重复,所以前2个空格匹配; 3.再次应用重复但第三个字符不是空格,所以回滚; 4.继续检查负面后视,匹配(没有空格btw当前字符和行首; 5.匹配是成功的。也许第4步开始... – clausavram

+0

你完全错过了它的事实不是先检查的'[\ t] +',而是后向检查,模式从左向右进行解析,反之亦然。步骤1:向后检查,如果检查结果为真,步骤2发生,匹配水平空格,一旦找到匹配,就从前一匹配的末尾开始搜索下一个匹配 –

总之

负回顾后只检查如果当前位置之前没有与反向预搜索模式和检查的结果是要么(是的,去匹配)或false(停止处理模式,继续下一场比赛)。检查不影响正则表达式索引,执行检查后,引擎保持在同一个位置。

在当前的表达式中,反向预搜索图案进行检查第一(作为图案被解析从左至右,而不是相反),并且仅当回顾后检查返回true [ \t]+图案试过。在第一个表达式中,当lookbehind模式找到匹配项(字符串的开始)时,反向 lookbehind返回false。第二个表达式为负 lookbehind返回为真,因为在字符串的开头没有字符串的开始,后跟1个或多个空格/制表符。

这里是2倍的表达背后的逻辑:

  • 的回顾后检查首先执行。在第一个表达式中,(?<!^[ \t]*)正尝试匹配字符串的开头。字符串的开头没有字符串的开始(^),后面跟着0+空格或制表符。重要的是要注意,在.NET中使用lookbehind实现会在相反方向检查字符串,翻转字符串并搜索零个或多个选项卡和字符串边界。在(?<!^[ \t]*)的情况下,lookbehind返回false,因为在0空格或制表符之前有一个开始位置(注意我们仍然位于字符串的开头)。第二个表达式looklookhind,(?<!^[ \t]+)返回true,因为字符串中第0个索引处的字符串开始之前没有制表符或空格,因此[ \t]+消费模式抓取前导水平空白。这将进一步移动正则表达式索引,并在稍后的字符串中找到另一个匹配项。

  • 在字符串开始处失败后,第一个表达式尝试在第一个空格后匹配。但是,(?<!^[ \t]*)返回false,因为字符串开始后跟1个空格(第一个)。同样的故事在第二个空间之后重复。与第一个(?<!^[ \t]*)[ \t]+表达式匹配的唯一空格是不在字符串开头的那些空格。

先行比喻

检查类似于超前模式:一个[ \t]+(?![ \t]+$)模式将"bb bb "发现无论空白块,而[ \t]+(?![ \t]*$)不会匹配字符串的结尾。相同的逻辑适用:1)*版本允许匹配空字符串,因此找到字符串的结尾并且负向预测返回false,匹配失败。当+版本遇到并消耗尾随空格时,停留在字符串末尾的正则表达式引擎无法找到一个或多个空格/制表符,然后是另一个字符串末尾,因此,负向预测返回true,并且尾随空白匹配。