【问题标题】:How to regex match a/b/c ...?如何正则表达式匹配 a/b/c ...?
【发布时间】:2015-02-20 20:20:32
【问题描述】:

如果我有一个像下面这样的数组,其中元素的顺序是随机的,并且每个元素可以有多少级别没有限制。这里只显示 3 个级别。 abc

我希望能够解析这样的数组,并将结果存储在像这样的哈希哈希中,当只有 3 个级别时

$VAR1 = {
          'a' => {
                   'b' => 'c'
                 }
        };

问题

我的问题是如何为此编写正则表达式,因为第一级末尾没有/,并且由于元素的顺序是随机的,如果a/b/c已经插入哈希,则元素 a 不应删除键 a 的哈希值。

这样的问题怎么解决?

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

my @ar = ("a", "a/b", "a/b/c");
my %h = ();

foreach my $a (@ar) {
}

【问题讨论】:

  • 如何处理"a" 输入?在这种情况下,值应该是什么并不明显,并且哈希不能只有一个键。
  • 如果这是您要解析的路径,请改用File::Spec 模块splitdir
  • 只是出于好奇,这些字符串实际上代表什么?正如 TLP 指出的文件路径,可能有更好的方法来处理它们,具体取决于它们是什么。
  • 但是如果值在 a 情况下应该是 undef,那么它也应该在 c 情况下 ({'a'=>{'b'=>{'c'=>undef}}})

标签: regex perl hash


【解决方案1】:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use Data::Diver 'DiveRef';

my @array = ("a", "a/b", "a/b/c");
my %hash = ();

foreach my $element (@array) {
    DiveRef( \%hash, \( split /\//, $element ) );
}

通常您会分配或修改 DiveRef 返回的标量引用(或分配给 DiveVal 的结果),但在这里您只想确保键存在。

\(...) 将 split 返回的列表转换为标量引用列表,这告诉 Data::Diver 这些总是哈希键,如果它们是数字则不可能是数组索引。

【讨论】:

    【解决方案2】:

    得到

    "a"                 => $tree = "a";
    "a", "a/b"          => $tree = { "a" => "b" };
    "a", "a/b", "a/b/c" => $tree = { "a" => { "b" => "c" } };
    "a", "a/b", "a/c"   => $tree = { "a" => { "b" => undef, "c" => undef } };
    

    代码:

    my $tree;
    for ("a", "a/b", "a/b/c") {
       my @keys = split qr{/};
       my $val = pop(@keys);
    
       my $p = \$tree;
       while (@keys) {
          my $key = shift(@keys);
          $$p = { $$p => undef } if !ref($$p);
          $p = \( ($$p)->{$key} );
       }
    
       if (defined($$p)) {
          $$p = { $$p => undef } if !ref($$p);
          ($$p)->{$val} = undef;
       } else {
          $$p = $val;
       }
    }
    

    但这不是一个好的数据结构,因为您需要使用ref 来导航它。相反,我建议

    "a"                 => $tree = { "a" => undef };
    "a", "a/b"          => $tree = { "a" => { "b" => undef } };
    "a", "a/b", "a/b/c" => $tree = { "a" => { "b" => { "c" => undef } } };
    "a", "a/b", "a/c"   => $tree = { "a" => { "b" => undef, "c" => undef } };
    

    代码:

    my $tree;
    for ("a", "a/b", "a/b/c") {
       my $p = \$tree;
       $p = \( ($$p)->{$_} ) for split qr{/};
    }
    

    看看构建这个数据结构有多简单?当您尝试导航时,您将获得类似的好处。


    请注意,您可以使用 Data::Diver 创建第二个数据结构(尽管我记得它要慢得多)。

    use Data::Diver qw( DiveRef );
    
    my $tree;
    for ("a", "a/b", "a/b/c") {
       DiveRef($tree //= {}, \split(qr{/}));
    }
    

    【讨论】:

      【解决方案3】:

      一个例子:

      my @ar = ("a", "a/b", "a/b/c");
      my %h;
      
      for (@ar) {
          my $levels = split /\//;
      
          for (my $i = 0; $i <= $#levels; $i++) {
              # How ever you want to set-up your hash of hashes
              # But each for loop iteration would give you a "level" of input
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2021-01-10
        • 2021-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-20
        • 2019-03-11
        • 2022-12-18
        相关资源
        最近更新 更多