Извлечение строки с регулярным выражением, хранящимся в хэше - PullRequest
2 голосов
/ 04 июля 2011

Я пытаюсь проанализировать определенные значения из текстового файла и вывести их в другой файл.

Я использую регулярные выражения, хранящиеся в хэше (в соответствии с их описательным именем), для поиска по строке (скаляр), а затем сохраняю обнаруженные значения в массиве, который затем записывается в файл.

У меня все работает, кроме части поиска / извлечения. (Я только недавно выучил Perl за последние пару дней, поэтому я не удивлюсь, если сделаю действительно простые ошибки.)

$inputstring = 'Lorem ipsum dolor Date: 20110131 quis semper egestas.';

%myregexhash = ( Date => '/([12][09][0-9][0-9][0-1][0-2][0-9][0-9])/' );

@foundvaluesarray=();

while ( ($thefieldname, $theregex) = each (%myregexhash))
{
    if ($inputstring =~ $theregex) 
    {
        push(@foundvaluesarray, "$thefieldname: $&\n");
        $inputstring = $';
    }
}

print "@foundvaluesarray";

Массив заполняется именами полей ("Date:"), но не значениями, которые я ищу ("20110131").

Есть идеи, что я делаю не так?

1 Ответ

6 голосов
/ 04 июля 2011

Сделайте одно небольшое изменение:

%myregexhash = ( Date => qr/([12][09][0-9][0-9][0-1][0-2][0-9][0-9])/ );

Обратите внимание на использование qr//, которое составляет регулярное выражение.

Вы новичок, поэтому я бы порекомендовал несколько других изменений.

Любая нетривиальная программа должна начинаться со следующего фронта:

#! /usr/bin/env perl

use strict;
use warnings;

Прагма strict имеет хорошие преимущества, такие как перехват имен переменных с ошибками во время компиляции и проверка использования ссылок. Прагма warnings включает дополнительную диагностическую диагностику, которая может предупредить вас о сомнительных случаях в вашем коде.

Теперь необходимо объявить заранее:

my $inputstring = 'Lorem ipsum dolor Date: 20110131 quis semper egestas.';

my %myregexhash = ( Date => qr/([12][09][0-9][0-9][0-1][0-2][0-9][0-9])/ );

my @foundvaluesarray=();

= () подразумевается в объявлении массива или хеша, поэтому вы не видите его в идиоматическом Perl.

Вы не хотите использовать $&, если можете помочь, потому что замедляет всю программу .

ПРЕДУПРЕЖДЕНИЕ: Как только Perl обнаружит, что вам нужен один из $&, $` или $' в любом месте программы, он должен предоставить их для каждого совпадения с образцом. Это может существенно замедлить вашу программу. Perl использует тот же механизм для создания $1, $2 и т. Д., Поэтому вы также платите цену за каждый шаблон, содержащий скобки с захватом. (Чтобы избежать этой стоимости при сохранении группового поведения, вместо этого используйте расширенное регулярное выражение (?: ... ).) Но если вы никогда не используете $&, $` или $', то шаблоны без захвата скобок не будут наказываться. Поэтому избегайте $&, $' и $`, если можете, но если вы не можете (и некоторые алгоритмы действительно ценят их), как только вы использовали их один раз, используйте их по своему желанию, потому что вы уже заплатил цену. Начиная с 5.005, $& не так дорого, как два других.

Поскольку вы окружили свой шаблон круглыми скобками, соответствующая подстрока записывается в $1, поэтому возьмите ее оттуда.

Кроме того, способ, которым вы отрубили переднюю часть $inputstring, гораздо более естественно выражен в Perl с s///.

while (my ($thefieldname, $theregex) = each (%myregexhash))
{
    if ($inputstring =~ s/$theregex//) 
    {
        push(@foundvaluesarray, "$thefieldname: $1\n");
    }
}

print "@foundvaluesarray";

Выход:

Date: 20110131
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...