2012-05-16 63 views
2

我想要一个正则表达式来匹配所有内容,但在一个更广泛的表达式中有几个特定的​​选项。(foo | bar | baz)相反

下面的例子将匹配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)的参数。所以我正在寻找一个可以在一个正则表达式中完成的答案,而不是多个链接在一起。

回答

6

您应该能够通过使用负先行做到这一点:

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

如果foobarbaz紧跟test_这将失败。

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

如果要接受类似test_fool.pltest_bart.pl,那么你可以将其更改为以下:

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

按秒打我。 +1 –

+0

我认为你的soution会拒绝'test_bart.pl',但正如我所理解的那样,OP将接受'test_bart.pl',而不是'test_bar.pl'(只是一个例子,注意与'bart'相关的特殊情况) ) – ArtM

+0

为了使这个仅*排除条件,你需要匹配表达式的结尾:'/ test _(?!(foo | bar | baz)\。pl)。* \。pl /'。 (如果字符串包含多个文件名(由于'。*'),这个版本也不正确,但在问题的上下文中不应该这样)。 – porges

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仅仅是用于获取的根据您的示例输入文件名列表。我只是替换了另一个匹配模式,这个模式适合我在目录中使用的文件。

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

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}) 
相关问题