我对贪婪的运算符在正面和负面的展望上感到困惑。

正向超前的脚本

foreach (<DATA>){
$_ = m/AAA.+(?=BBB)/g;
print "$&\n";
}
__DATA__
AAA 1121 BBB
AAA 443  CCC
AAA 4431 BBB
ABC 321  EACA
AAA 321  BBB
ACD 431 MAKN
AAA 751  ABC

它的输出
AAA 1121

AAA 4431

AAA 321

负前瞻
foreach (<DATA>){
$_ = m/AAA.+(?!BBB)/g;
print "$&\n";
}

它的输出
AAA 1121 BBB
AAA 443  CCC
AAA 4431 BBB

AAA 321  BBB

AAA 751  ABC

在执行negative lookahed时,不要考虑(?!BBB)。因为我在(?!BBB)之前使用贪婪运算符。在这种情况下,正向期望贪婪运算符会考虑使用(?=BBB)。为什么给出不同的结果?

我可以通过代码$_ = m/AAA\s\d+(?!.+BBB)/g;轻松实现OP。

但是我不知道我的代码执行什么?

最佳答案

让我们考虑第一个示例:

AAA 1121 BBB
\_/\_______/^
 |     |    |
 |     |    +--- this (the empty string right there) satisfies (?!BBB)
 |     |
 |     +-------- matched by .+
 |
 +-------------- matched by AAA

这是因为贪婪的.+会消耗1121 BBB ,其中包括BBB。在使用完该行的其余部分之后,针对剩余的空字符串检查(?!BBB)。而且此空字符串满足(?!BBB),因为它后面没有BBB吗?

负前瞻

该算法执行如下。 ^是当前位置(字符串中存在当前位置,并且模式中存在当前位置(种类))。
  • 初始状态:
    AAA 1121 BBB          AAA.+(?!BBB)
    ^                     ^
    
  • 匹配AAA
    AAA 1121 BBB          AAA.+(?!BBB)
       ^                     ^
    
  • 匹配.+
    AAA 1121 BBB          AAA.+(?!BBB)
                ^              ^
    
  • 检查(?!BBB)
    AAA 1121 BBB          AAA.+(?!BBB)
                ^                     ^
    
  • 此位置没有BBB匹配=>成功!
    AAA 1121 BBB
    \__________/
    


  • 积极向前

    现在,让我们看看为什么AAA.+(?=BBB)精确地产生匹配:
  • 初始状态:
    AAA 1121 BBB          AAA.+(?=BBB)
    ^                     ^
    
  • 匹配AAA
    AAA 1121 BBB          AAA.+(?=BBB)
       ^                     ^
    
  • 匹配.+
    AAA 1121 BBB          AAA.+(?=BBB)
                ^              ^
    
  • 检查(?=BBB)
    AAA 1121 BBB          AAA.+(?=BBB)
                ^              ^
    

    此位置没有BBB匹配=>回溯(通过.+少消耗一个字符)
  • 检查(?=BBB)
    AAA 1121 BBB          AAA.+(?=BBB)
               ^               ^
    

    此位置没有BBB匹配=>回溯(通过.+少消耗一个字符)
  • 检查(?=BBB)
    AAA 1121 BBB          AAA.+(?=BBB)
              ^                ^
    

    此位置没有BBB匹配=>回溯(通过.+少消耗一个字符)
  • 检查(?=BBB)
    AAA 1121 BBB          AAA.+(?=BBB)
             ^                        ^
    
  • 我们在此位置确实有一个BBB匹配=>成功!
    AAA 1121 BBB
    \_______/
    
  • 08-18 20:18
    查看更多