我有一个如下所示的列表:
__DATA__
49103393193[0-9]{1,3};+49103/393193-0;Company 1;Street;Number;Postal Code;City
现在我将带有这些值的大列表加载到一个Hash中,如下所示:
%voicePrefix = (
'49103393193[0-9]{1,3}' => [
'+49103/393193-0',
'Company 1',
'Street'
'Number'
'Postal Code'
'City'
],
);
我是这样做的:
my %voicePrefix = map {
chomp;
my @fields = split ';';
shift @fields => \@fields;
} __DATA__;
my $voiceRegex = '(' . join('|',map{quotemeta} keys %voicePrefix) . ')';
现在的问题是我有另一个包含大量数字的列表,所以我可以说我在@lines中加载了一个文件,如下所示:
__@lines__
4910339319344;Test 1
49103393193411;Test 2
49103393193941;Test 3
现在我想要做的是使用正则表达式对我这样做的数字,但是这样做它从未找到匹配的工作
my @lines = __FILEUPTHERE__;
my @line;
my $company;
for(my $i = 0; i < @lines; $i++)
{
#Split Line
@line = split( /,/, $lines[$i] );
#NO MATCH HERE
$company = $voicePrefix{$1}[1] if ($line[0] =~ /$voiceRegex/);
}
我希望有人可以帮我解决这个问题。
谢谢:)
答案 0 :(得分:2)
在构造正则表达式时使用quotemeta
,这意味着所有哈希键都将在正则表达式中按字面处理。您正在寻找文字字符串49103393193[0-9]{1,3}
,而不是数字后跟1-3位数。
删除map{quotemeta}
,你应该没问题。
注意:如果输入不是来自受信任的来源,则从输入中获取正则表达式是一个安全漏洞。
更新:此外,您几乎不需要在Perl中使用C风格的for
循环。他们应该避免。代替:
foreach my $line (@lines)
{
#Declare a variable here if you are using it here.
my @fields = split( /,/, $line );
$company = $voicePrefix{$1}[1] if ($fields[0] =~ /$voiceRegex/);
}
更新2:您还可能希望向正则表达式添加锚点,以确保匹配确切的字符串,而不是较长字符串的子集:/^$voiceRegex$/
。< / p>
更新3:通过这些更正,匹配有效。但是,您还有一个问题,即您尝试将匹配的号码用作voicePrefix
的键。但是,这不起作用,因为voicePrefix的键是正则表达式,而不是可能匹配此类正则表达式的数字。需要改变您的设计。最简单的方法是不创建一个大的正则表达式,而只是测试每个键以查看是否匹配:
foreach my $line (@lines)
{
#Declare a variable here if you are using it here.
my @fields = split( /;/, $line );
foreach my $regex (keys %voicePrefix)
{
$company = $voicePrefix{$regex}[1] if ($fields[0] =~ /$regex/);
}
}