2

我想要一个正则表达式来匹配除更广泛表达式中的一些特定选项之外的所有内容。

以下示例将匹配 test_foo.pl 或 test_bar.pl 或 test_baz.pl:

/test_(foo|bar|baz)\.pl/

但我想恰恰相反:

match test_.*\.pl except for where .* = (foo|bar|baz)

我对此的选择有点有限,因为这不是直接进入 perl 程序,而是cloc 的一个参数,一个计算代码行数的程序(恰好是用 perl 编写的)。所以我正在寻找一个可以在一个正则表达式中完成的答案,而不是多个链接在一起的答案。

4

4 回答 4

6

您应该能够通过使用负前瞻来完成此操作:

/test_(?!foo|bar|baz).*\.pl/

如果foobarbaz紧随其后,这将失败test_

请注意,这仍然可以匹配类似的test_notfoo.pl内容,并且会失败test_fool.pl,如果您不想要这种行为,请通过添加一些确切应该和不应该匹配的示例来澄清。

如果您想接受类似test_fool.plortest_bart.pl的内容,则可以将其更改为以下内容:

/test_(?!(foo|bar|baz)\.pl).*\.pl/
于 2012-05-16T21:11:43.527 回答
1
(?:(?!STR).)*

STR

作为

[^CHAR]

CHAR

所以你要

if (/^test_(?:(?!foo|bar|baz).)*\.pl\z/s)

更具可读性:

my %bad = map { $_ => 1 } qw( foo bar baz );

if (/^test_(.*)\.pl\z/s && !$bad{$1})
于 2012-05-17T04:48:07.223 回答
1
#!/usr/bin/env perl

use strict; use warnings;

my $pat = qr/\Atest_.+(?<!foo|bar|baz)[.]pl\z/;

while (my $line = <DATA>) {
    chomp $line;
    printf "%s %s\n", $line, $line =~ $pat ? 'matches' : "doesn't match";
}


__DATA__
test_bar.pl
test_foo.pl
test_baz.pl
test baz.pl
0test_bar.pl
test_me.pl
test_me_too.txt

输出:

test_bar.pl 不匹配
test_foo.pl 不匹配
test_baz.pl 不匹配
测试 baz.pl 不匹配
0test_bar.pl 不匹配
test_me.pl 匹配
test_me_too.txt 不匹配

于 2012-05-16T21:45:42.467 回答
0

嗯,我可能误解了你的问题。无论如何,也许这有帮助......


您将否定匹配运算符。例如:

perl -lwe "print for grep ! m/(lwp|archive).*\.pl/, glob q(*.pl)"
# Note you'd use single-quotes on Linux but double-quotes on Windows.
# Nothing to do with Perl, just different shells (bash vs cmd.exe).

!否定比赛。以上是以下的简写:

perl -lwe "print for grep ! ($_ =~ m/(lwp|archive).*\.pl/), glob q(*.pl)"

也可以使用否定匹配运算符来编写!~,如下所示:

perl -lwe "print for grep $_ !~ m/(lwp|archive).*\.pl/, glob q(*.pl)"

如果您想知道,glob根据您的示例,它只是用于获取文件名的输入列表。我刚刚替换了另一种匹配模式,该模式适合我在目录中方便使用的文件。

于 2012-05-16T21:18:21.870 回答