(foo | bar | baz)对面

时间:2012-05-16 21:08:13

标签: regex perl

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

以下示例将匹配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, a program that counts lines of code (that happens to be written in perl)的参数。所以我正在寻找一个可以在一个正则表达式中完成的答案,而不是多个链接在一起。

4 个答案:

答案 0 :(得分:6)

您应该能够通过使用否定前瞻来实现这一目标:

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

如果foobarbaz紧跟test_后,这将失败。

请注意,这仍然可能与test_notfoo.pl匹配,并且会在test_fool.pl上失败,如果您不想要这种行为,请通过添加一些确切应该和不应该匹配的示例来澄清。< / p>

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

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

答案 1 :(得分: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 doesn't match
test_foo.pl doesn't match
test_baz.pl doesn't match
test baz.pl doesn't match
0test_bar.pl doesn't match
test_me.pl matches
test_me_too.txt doesn't match

答案 2 :(得分: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})

答案 3 :(得分: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只是用于根据您的示例获取文件名的输入列表。我只是替换了另一种适合我在目录中使用的文件的匹配模式。