2013-02-18 56 views
0

我执行下面的代码:正则表达式不匹配按预期

#!/usr/bin/perl -w 

my $filter1="^p1c|^p2c|^p3c|^p11c|^p23c|^p105csi1m1|^p105csi1m2|^p105csi1m13|^p105csi2m14|^p101csi1m1|^p101csi1m2|^p101csi1m13|^p101csi2m14|^p103csi1m1|^p103csi1m2|^p103csi1m13|^p103csi2m16|^p102csi1m1|^p102csi1m2|^p102csi1m13|^p102csi2m16|^p100csi1m4|^p100csi1m5|^p100csi2m13|^p100csi1m14"; 
my $filter2="^p105csi2m13|^p105csi1m14"; 

$n1="p105csi1m14"; 

my $m1 .= "$n1 " if($n1 =~ m/$filter1/); 
my $m2 .= "$n1 " if($n1 =~ m/$filter2/); 

print "\nmatch 1 => $m1\n"; 
print "\nmatch 2 => $m2\n"; 

从上面的代码的输出如下:

match 1 => p105csi1m14 

match 2 => p105csi1m14 

预期的结果是如下:

match 1 => 

match 2 => p105csi1m14 

我不确定它为什么会这样。有人可以帮助解决上述问题吗?

+2

'p105csi1m1'是'p105csi1m14'的子字符串。 – 2013-02-18 15:35:59

+0

正则表达式^^p105csi1m1'匹配你的字符串。你打算在正则表达式的末尾有一个'$'吗? – geoffspear 2013-02-18 15:36:21

+0

啊..有帮助...非常感谢 – user2083779 2013-02-18 15:43:24

回答

1

它是匹配的,因为它以p105csi1m1开头;该标准将出现在您提供的两个过滤器中。

4

您未定义匹配的结尾,p105csi1m1p105csi1m14的子字符串。

解决的办法是将$添加到正则表达式来表示该行的结尾。此外,通过使用组可以使其更具可读性并为您节省大量的^$字符。

my $filter1="^(p1c|...|p105csi1m1)$"; 
my $filter2="^(p105csi2m13|p105csi1m14)$"; 
1

对于自己而言,一件事就是让事情变得困难。你的正则表达式匹配比它应该多,因为它只锚定在字符串的开头。您还需要将它锚定在最后以避免部分匹配。此外,你有很多重复的文字可以简化为:

my @words = qw(p1c p2c p3c p11c p23c p105csi1m1 p105csi1m2 p105csi1m13 
       p105csi2m14 p101csi1m1 p101csi1m2 p101csi1m13 p101csi2m14 
       p103csi1m1 p103csi1m2 p103csi1m13 p103csi2m16 p102csi1m1 
       p102csi1m2 p102csi1m13 p102csi2m16 p100csi1m4 p100csi1m5 
       p100csi2m13 p100csi1m14); 
my $filter1 = '^(?:' . join('|', @words) . ')$'; 

虽然这可能是更好的哈希查找解决:

my %lookup = map { $_ => 1 } @words; # create a key for each word 
my $m1 .= "$n1 " if($lookup{$n1});  # check if key exists 

需要注意的是哈希键完全匹配,这样你就不会正则表达式具有任何灵活性。但在这种情况下,看起来这是件好事。