Perl解析带有一个或多个字段的字符串

时间:2011-11-25 22:57:45

标签: regex perl

我有一个我需要解析的字符串。它符合以下要求:

  • 它由0个或更多个key->值对组成。
  • 密钥总是2个字母。
  • 该值是一个或多个数字。
  • 键和值之间不会有空格。
  • 各对之间可能有也可能没有空格。

我可能会看到示例字符串:

  • AB1234 //一个键 - >值对(Key = AB,Value = 1234)
  • AB1234 BC2345 //两个键 - >值对,以空格分隔
  • AB1234BC2345 //两个key->值对,不以空格分隔
  • //空Sting,无键 - >值对
  • AB12345601BC1234CD1232PE2343 //许多键 - >值对,没有空格
  • AB12345601 BC1234 CD1232 PE2343 //许多key->值对,带空格

我需要构建此字符串的Perl哈希值。如果我能保证它是1对,我会做这样的事情:

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

对于多个字符串,我可以做一些事情,在上述正则表达式的每次匹配之后,我获取原始字符串的子字符串(免除第一个匹配),然后再次搜索。但是,我确信有一种更聪明,更为方便的方式来实现这一目标。

希望我没有这么糟糕的数据源来处理 -

乔纳森

3 个答案:

答案 0 :(得分:8)

在带有全局标志的列表上下文中,正则表达式将返回all matched substrings

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;

答案 1 :(得分:3)

你已经在那里了:

$hash{$1} = $2 while $string =~ /([[:alpha:]]{2})([0-9]+)/g

答案 2 :(得分:0)

假设您的字符串绝对符合您的方案(即不会有A122ABC123形式的任何字符串,那么这应该有效:

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