贪婪的算子结果在正面和负面前瞻性方面有所不同吗?

mkH*_*Hun 3 regex perl

我对正面和负面的贪婪的操作员感到困惑.

积极前瞻的脚本

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
Run Code Online (Sandbox Code Playgroud)

这是输出

AAA 1121 

AAA 4431 

AAA 321  
Run Code Online (Sandbox Code Playgroud)

否定前瞻

foreach (<DATA>){
$_ = m/AAA.+(?!BBB)/g; 
print "$&\n";
} 
Run Code Online (Sandbox Code Playgroud)

这是输出

AAA 1121 BBB
AAA 443  CCC
AAA 4431 BBB

AAA 321  BBB

AAA 751  ABC
Run Code Online (Sandbox Code Playgroud)

在执行中negative lookahed不考虑(?!BBB).因为我正在使用之前的贪婪运算符(?!BBB).在那种情况下,积极向前看贪婪的运营商考虑(?=BBB).这就是为什么给出不同的结果?

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

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

Luc*_*ski 8

让我们考虑第一个例子:

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

这是因为贪婪的.+消耗1121 BBB ,包括了BBB.消耗剩余的线后,(?!BBB)检查剩余的空字符串.这个空字符串满足,(?!BBB)因为它没有跟着BBB?


消极的向前看

算法执行如下.^是当前位置(字符串中有当前位置,模式中有当前位置(种类)).

  1. 初始状态:

    AAA 1121 BBB          AAA.+(?!BBB)
    ^                     ^
    
    Run Code Online (Sandbox Code Playgroud)
  2. 比赛 AAA

    AAA 1121 BBB          AAA.+(?!BBB)
       ^                     ^
    
    Run Code Online (Sandbox Code Playgroud)
  3. 比赛 .+

    AAA 1121 BBB          AAA.+(?!BBB)
                ^              ^
    
    Run Code Online (Sandbox Code Playgroud)
  4. 校验 (?!BBB)

    AAA 1121 BBB          AAA.+(?!BBB)
                ^                     ^
    
    Run Code Online (Sandbox Code Playgroud)
  5. BBB在这个位置没有匹配=>成功!

    AAA 1121 BBB
    \__________/
    
    Run Code Online (Sandbox Code Playgroud)

积极的向前看

现在,让我们来看看为什么恰好 AAA.+(?=BBB)产生匹配:

  1. 初始状态:

    AAA 1121 BBB          AAA.+(?=BBB)
    ^                     ^
    
    Run Code Online (Sandbox Code Playgroud)
  2. 比赛 AAA

    AAA 1121 BBB          AAA.+(?=BBB)
       ^                     ^
    
    Run Code Online (Sandbox Code Playgroud)
  3. 比赛 .+

    AAA 1121 BBB          AAA.+(?=BBB)
                ^              ^
    
    Run Code Online (Sandbox Code Playgroud)
  4. 校验 (?=BBB)

    AAA 1121 BBB          AAA.+(?=BBB)
                ^              ^
    
    Run Code Online (Sandbox Code Playgroud)

    BBB在这个位置没有匹配=> Backtrack(消耗少一个char .+)

  5. 校验 (?=BBB)

    AAA 1121 BBB          AAA.+(?=BBB)
               ^               ^
    
    Run Code Online (Sandbox Code Playgroud)

    BBB在这个位置没有匹配=> Backtrack(消耗少一个char .+)

  6. 校验 (?=BBB)

    AAA 1121 BBB          AAA.+(?=BBB)
              ^                ^
    
    Run Code Online (Sandbox Code Playgroud)

    BBB在这个位置没有匹配=> Backtrack(消耗少一个char .+)

  7. 校验 (?=BBB)

    AAA 1121 BBB          AAA.+(?=BBB)
             ^                        ^
    
    Run Code Online (Sandbox Code Playgroud)
  8. 我们确实BBB在这个位置有一场比赛=>成功!

    AAA 1121 BBB
    \_______/
    
    Run Code Online (Sandbox Code Playgroud)