2013-02-20 4 views
0

У меня есть список, который выглядит следующим образом:Regex не находит матч

__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) . ')'; 

Теперь проблема у меня есть еще один список с большим количеством цифр так что позволяет сказать, что я загрузил файл, чтобы @line s, который выглядит следующим образом:

[email protected]__ 
4910339319344;Test 1 
49103393193411;Test 2 
49103393193941;Test 3 

Теперь то, что я хочу сделать, это использовать регулярные выражения на число я делаю это так, но doesent работать он никогда не находит совпадение

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/); 
} 

Я надеюсь, кто-то может помочь мне с этой проблемой.

Спасибо :)

ответ

2

Вы используете quotemeta при построении регулярных выражений, а это значит, что все ваши ключи хеша будет рассматриваться буквально в регулярном выражении. Вы ищите буквенную строку 49103393193[0-9]{1,3}, вместо номера, за которым следует 1-3 цифры.

Удалите map{quotemeta}, и все должно быть в порядке.

Примечание: получение регулярных выражений со входа является защитным отверстием, если вход не поступает из надежного источника.

Update: Кроме того, вы почти никогда не нуждаются в стиле С for петель в Perl. Их следует избегать. Вместо этого:

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/); 
} 

Update 2: Вы также можете добавить якоря в свое регулярное выражение, чтобы убедиться, что вы согласование точной строки, а не подмножество более длинной строки: /^$voiceRegex$/.

Обновление 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/); 
    } 
} 
+0

Я сделал это сейчас с моим $ voiceRegex = «(» Join («|», ключи% voicePrefix). ')'; но он все еще оставил – alexj

+0

@alexj, возникла другая проблема с вашим кодом. См. Обновление моего ответа. – 2013-02-20 11:33:17

+0

Спасибо, что это работает, но разве это невозможно сделать в одном регулярном выражении, потому что ваше последнее решение замедляет мой код, мой 6x потребовалось 20 секунд с одним регулярным выражением, и так требуется 120 секунд? – alexj

Смежные вопросы