Perl正则表达式负面后瞻

emx*_*emx 3 regex perl negative-lookbehind

试图在正则表达式处理中包围前瞻和后.

假设我有一个列出PID和其他内容的文件.我想构建一个正则表达式来匹配PID格式\ d {1,5},但这也排除了某个PID.

$myself = $$;
@file = `cat $FILE`;
@pids = grep /\d{1,5}(?<!$myself)/, @file;
Run Code Online (Sandbox Code Playgroud)

在这个正则表达式中,我尝试使用(?<!TO_EXCLUDE)构造使用负面后视将数字匹配与排除组合.这不起作用.

样本文件:

456
789
4567
345
22743
root
bin
sys
Run Code Online (Sandbox Code Playgroud)

如果有人能指出我正确的方向,我将不胜感激.

也有兴趣了解这种负面观察是否会在这种情况下最有效.

cho*_*oba 6

"看后面"真的看起来很落后.因此,您可以检查PID是否先于某些内容,而不是它是否与某些内容匹配.如果您只想排除$$,您可以更直接:

@file = `cat $FILE`;
@pids = grep /(\d{1,5})/ && $1 ne $$, @file;
Run Code Online (Sandbox Code Playgroud)


rai*_*7ow 5

我赞成了choroba解决方案,只想解释为什么你原来的方法不起作用.

看,正则表达式解析器是一个复杂的野兽:它试图匹配尽可能多的符号 - 并试图不惜任何代价匹配的内部斗争.而后者通常会获胜.)

例如,让我们分析以下内容:

my $test_line = '22743';
my $pid = '22743';
print 'Matched?', "\n" if $test_line =~ /\d{1,5}(?<!$pid)/;
print $&, "\n";
Run Code Online (Sandbox Code Playgroud)

为什么打印'匹配',你可能会问?因为这就是发生的事情:首先引擎试图消耗所有五个数字,然后匹配下一个子表达式 - 并且失败了(这是负面的后观点,不是吗?)

如果是你,你已经停止了 - 但不是引擎!它仍然感觉到无与伦比的黑暗欲望 - 什么!因此,它需要下一个可能的量词 - 四个而不是五个 - 当然,现在,后向子表达式注定要成功.通过检查打印的内容,可以很容易地检查print $&;

它可以在正则表达式的范围内解决吗?是的,所谓的atomics:

print 'No match for ya!', "\n" unless $test_line =~ /(?>\d{1,5})(?<!$pid)/;
Run Code Online (Sandbox Code Playgroud)

但我猜这通常被认为是一种黑魔法.)