Perl Parse String с одним или несколькими полями - PullRequest
4 голосов
/ 26 ноября 2011

У меня есть строка, которую мне нужно проанализировать.Он соответствует следующим требованиям:

  • Он состоит из 0 или более пар ключ -> значение.
  • Ключ всегда состоит из 2 букв.
  • Значение - одно или несколько чисел.
  • Между ключом и значением не будет пробела.
  • Между отдельными парами может быть или не быть пробела.

Примеры строк, которые я вижу:

  • AB1234 // Одна пара ключ-> значение (Ключ = AB, Значение = 1234)
  • AB1234 BC2345// Две пары ключ-> значение, разделенные пробелом
  • AB1234BC2345 // Две пары ключ-> значение, не разделенные пробелом
  • // Пустые пары Sting, No key-> value
  • AB12345601BC1234CD1232PE2343 // Множество пар ключ-> значение, без пробела
  • AB12345601 BC1234 CD1232 PE2343 // Множество пар ключ-> значение, с пробелами

Iнужно построить Perl-хеш этой строки.Если бы я мог гарантировать, что это была 1 пара, я бы сделал что-то вроде этого:

$string =~ /([A-Z][A-Z])([0-9]+)/
$key = $1
$value = $2
$hash{$key} = $value

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

Жаль, что у меня не было такого дерьмового источника данных, чтобы иметь дело с -

Jonathan

Ответы [ 3 ]

8 голосов
/ 26 ноября 2011

В контексте списка с глобальным флагом регулярное выражение вернет все подходящие подстроки :

use Data::Dumper;

@strs = (
    'AB1234',
    'AB1234 BC2345',
    'AB1234BC2345',
    '',
    'AB12345601BC1234CD1232PE2343',
    'AB12345601 BC1234 CD1232 PE2343'
);

for $str (@strs) {
    # The money line
    %parts = ($str =~ /([A-Z][A-Z])(\d+)/g);

    print Dumper(\%parts);
}

Для большей непрозрачности удалите скобки вокруг сопоставления с образцом: %parts = $str =~ /([A-Z][A-Z])(\d+)/g;.

3 голосов
/ 26 ноября 2011

Вы уже там:

$hash{$1} = $2 while $string =~ /([[:alpha:]]{2})([0-9]+)/g
0 голосов
/ 26 ноября 2011

Предполагая, что ваши строки определенно будут соответствовать вашей схеме (то есть не будет никаких строк вида A122 или ABC123), тогда это должно работать:

my @strings = ( 'AB1234', 'AB1234 BC2345', 'AB1234BC2345' );

foreach my $string (@strings) {
    $string =~ s/\s+//g;
    my ( $first, %elems ) = split(/([A-Z]{2})/, $string);
    while (my ($key,$value) = each %elems) {
        delete $elems{$key} unless $key =~ /^[A-Z]{2}$/;
        delete $elems{$key} unless $value =~ /^\d{4}$/;
    }
    print Dumper \%elems;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...