正则表达式不符合预期

时间:2013-02-18 15:32:44

标签: perl

我正在执行以下代码:

#!/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

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

3 个答案:

答案 0 :(得分:4)

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

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

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

答案 1 :(得分:1)

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

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

请注意,哈希键完全匹配,因此您将无法获得正则表达式带来的任何灵活性。但在这种情况下,看起来这是件好事。