【问题标题】:Perl parse String with one or more fieldsPerl 用一个或多个字段解析字符串
【发布时间】:2012-01-06 16:16:16
【问题描述】:

我有一个字符串需要解析。满足以下要求:

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

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

  • AB1234 //一个key->value对(Key=AB, Value=1234)
  • AB1234 BC2345 //两个key->value对,用空格隔开
  • AB1234BC2345 //两个key->value对,不用空格分隔
  • //空字符串,没有键->值对
  • AB12345601BC1234CD1232PE2343 //很多key->value对,没有空格
  • AB12345601 BC1234 CD1232 PE2343 //很多key->value对,有空格

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

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

对于多个字符串,我可能会做一些事情,在上述正则表达式的每次匹配之后,我获取原始字符串的子字符串(排除第一个匹配项),然后再次搜索。不过,我确信有一种更聪明的 perl-esque 方式来实现这一点。

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

乔纳森

【问题讨论】:

标签: regex perl


【解决方案1】:

在带有全局标志的列表上下文中,正则表达式将返回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;

【讨论】:

    【解决方案2】:

    你已经在那里了:

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

    【讨论】:

      【解决方案3】:

      假设您的字符串肯定会匹配您的方案(即不会有任何形式为 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;
      }
      

      【讨论】:

      • 纯正则表达式的答案看起来更干净一些。我只是在尝试与split 不同的东西。 :-)
      • 如果所有内容都在一个字符串中,您可以执行类似$string =~ s/\s+//g; my %h = map{split/(?<=\D)(?=\d)/}split/(?<=\d)(?=\D)/, $string;
      • 或者干脆%h = split /\s*(\d+)\s*/, $string
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-19
      • 2014-07-19
      • 2019-10-27
      • 1970-01-01
      • 1970-01-01
      • 2013-08-09
      • 1970-01-01
      相关资源
      最近更新 更多