【问题标题】:How do you map regex string replacement values ($1,$2 etc) to a hash?如何将正则表达式字符串替换值($1、$2 等)映射到哈希?
【发布时间】:2012-01-09 05:00:44
【问题描述】:
my (@keys,@values) = ($text =~ /\{IS\:([a-zA-Z0-9_-]+)\}(.*)\{\\IS\:([a-zA-Z0-9_-]+)\}/g);

应该匹配这样的字符串

{IS:cow}moo{\IS:cow}
{IS:cow}moo{\IS:cow}    
{IS:dog}bark{\IS:dog}
{IS:dog}meow{\IS:dog} #probably not a dog

这很好,除了所有的 $1、$2 和 $3 值都被转储到 @keys 中......所以我试图弄清楚如何让这些家伙进入一个很好的 $1 => $2 对的哈希值...... .

对于完整的上下文,我真正想要做的是让正则表达式返回一个看起来像的数据结构(并附加一个计数找到密钥的次数)

{ 
  cow_1 => moo,
  cow_2 => moo,
  dog_1 => bark,
  dog_2 => meow,
}

有没有办法通过正则表达式使用 map{ } 函数来完成此任务?大概是这样的吧?

my %datahash = map { ( $1 eq $3 ) ? { $1 => $2 } : undef } @{ regex...};

$1 等于 $3 以确保它是一个匹配的标签(无需递归检查这些标签没有嵌套),如果是这样,则使用 $1 作为键和 $2 作为值;

然后对于这些键 => 值对中的每一个,我想替换

{IS:cow}moo{\IS:cow}
{IS:cow}moo{\IS:cow}   

与

{cow_1}
{cow_2}

那么如果 $cachedData{cow} 为真,所有的 cow_* 都将被替换为它们在 %datahash 中的键...

【问题讨论】:

    标签: regex perl hash map


    【解决方案1】:
    $hash{$1} = $2 while 
            $text =~ /\{IS\:([a-zA-Z0-9_-]+)\}
                               (.*)
                      \{\\IS\:([a-zA-Z0-9_-]+)\}/gx;
    

    (添加/x 修饰符以提高可读性)

    【讨论】:

    • 这很好,/x 修饰符有什么作用?
    • @nodebunny 它会忽略空格,因此可以很好地格式化正则表达式。
    【解决方案2】:

    我从正则表达式中删除了无用的反斜杠和括号,并在 char 类中使用了快捷方式:

    #!/usr/bin/perl
    use warnings;
    use strict;
    
    my $text = '{IS:cow}moo{\IS:cow}
    {IS:cow}moo{\IS:cow}    
    {IS:dog}bark{\IS:dog}
    {IS:dog}meow{\IS:dog}';
    
    my %cnt;
    my %animals;
    while ( $text =~ /\{IS:([\w-]+)}(.*)\{\\IS:[\w-]+}/g ){
        $animals{$1 . '_' . ++$cnt{$1}} = $2;
    }
    
    print "$_ => $animals{$_}\n" for sort keys %animals;
    

    【讨论】:

    • 如果你想确保开始/结束标签匹配,然后在正则表达式中使用反向引用:/\{IS:([\w-]+)}(.*)\{ \\IS:\1}/g
    【解决方案3】:
    • $dataHash{cow}[$num] 完全等同于 $dataHash{"cow_$num"}
    • 使用 $dataHash{cow} 以及相对于 使用
      @dataHash{ grep { m/^cow_/ } keys %dataHash }
      “扫描”键
      • 它还将源数据(“cow”)与合成数据(“1”分开,因为这是我第一次看到这个。)

    所以,我认为现在是让multi_hash 发挥作用的好时机。

    sub multi_hash {
        use List::Pairwise qw<mapp>;
        my %h;
        mapp { push @{ $h{ $a } }, $b } @_;
        return wantarray ? %h : \%h;
    }
    

    使用该习语,您可以创建一个哈希,类似于您想要的:

    my %dataHash 
        = multi_hash(  map { m/[{]IS:([\w-]+)[}]([^{]+)[{]\\IS:\1[}]/ } @lines )
        ;
    

    这给了我:

    %dataHash: {
                 cow => [
                          'moo',
                          'moo'
                        ],
                 dog => [
                          'bark',
                          'meow'
                        ]
               }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-13
      • 2017-02-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多