Perl 中的负向回顾断言

5

我有一组文件路径,希望列出所有不包含x/y/z/的文件路径。另一个限制是我不能使用print if !m{x/y/z/},因为我没有脚本的写权限。我可以提供用于包含(作为命令行选项)的正则表达式模式,即将打印匹配的所有内容。

这是我的尝试。我正在尝试匹配所有在它们前面具有x/y/z/的行。

#!/usr/bin/perl
use warnings;
use strict;

while(<DATA>) {
   print if m{(?<!x/y/z/).*};
}

__DATA__
x/y/z/a/b/x.cc
x/y/z/a/b/x.cc
x/y/z/a/b/x.cc
x/y/a/b/m.cc
x/y/a/b/m.cc

我期望它只会打印底部两个字符串,但实际上它打印了全部内容。但是当我将模式更改为(?<=x/y/z/).*时,它仅打印前三个字符串。
x/y/z/a/b/x.cc
x/y/z/a/b/x.cc
x/y/z/a/b/x.cc

为什么会这样,我应该如何修复我的正则表达式?

m{(?<!x/y/z/).*} 匹配 x/y/z/a/b/x.cc 是因为 m{(?<!x/y/z/).*} 匹配 /y/z/a/b/x.cc - ikegami
1个回答

4
你需要的是一个“负向先行断言”。因此,直接从修道院获得答案:
#!/usr/bin/perl
use warnings;
use strict;

while(<DATA>) {
   print if m{^(?!(?s:.*)x/y/z)}; 
}

__DATA__
x/y/z/a/b/x.cc
x/y/z/a/b/x.cc
x/y/z/a/b/x.cc
x/y/a/b/m.cc
x/y/a/b/m.cc

2
匹配一个不以任何数量的任何字符开头,后跟 x/y/z 的字符串。 - ysth
2
你真的想要过滤掉 x/y/zoo/a.cc 吗?需要添加 /(?:/|\z) - ikegami
不,我不想过滤掉 x/y/zoox/y/z/ 下的所有内容都应该被过滤掉。让我适当地编辑一下问题。 - Unos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接