2

因此,我试图根据 foreach 中的正则表达式对数组进行哈希处理。

我得到了一些文件路径,它们的格式是:

longfilepath/name.action.gz

所以基本上会有同名但动作不同的文件,所以我想用作为动作数组的名称键进行哈希。我显然做错了什么,因为我在运行代码时不断收到此错误:

Not an ARRAY reference at ....the file I'm writing in

我没有得到,因为我正在检查它是否设置,如果没有将它声明为数组。我仍然习惯 perl,所以我猜我的问题很简单。

我还应该说,我已经验证了我的正则表达式正确地生成了“名称”和“动作”字符串,所以问题肯定出在我的 foreach 中;

谢谢你的帮助。:)

我的代码就是这样。

my %my_hash;
my $file_paths = glom("/this/is/mypath/*.*\.gz"); 
foreach my $path (@$bdr_paths){

    $path =~ m"\/([^\/\.]+)\.([^\.]+)\.gz";

    print STDERR "=>".Dumper($1)."\n\r";
    print STDERR "=>".Dumper($2)."\n\r";

    #add the entity type to a hash with the recipe as the key
    if($my_hash{$1})
    {
        push($my_hash{$1}, $2);
    }
    else
    {
        $my_hash{$1} = ($2);
    }

}
4

2 回答 2

2

glob,不是glom。在 glob 表达式中,句点不是元字符。→ glob '/this/is/mypath/*.gz'

使用备用正则表达式分隔符的全部原因是避免不必要的转义。正斜杠不是正则表达式元字符,而是分隔符。在 charclass 中,许多运算符失去了它们的特殊性;没有必要逃避这个时期。因此m!/([^/.]+)\.([^.]+)\.gz!

不要附加\n\r到您的输出中。① 该Dumper函数已经添加了一个换行符。② 如果您在一个需要 CRLF 的操作系统上,则使用:crlfPerlIO 层,它将所有\ns 转换为 CRLF。您可以通过添加图层binmode STDOUT, ':crlf'。③ 如果你在做网络,最好指定你想要发出的确切字节,例如\x0A\x0D\012\015。(但在这种情况下,还要删除所有 PerlIO 层)。

使用引用作为第一个 arg topush不适用于早于 v5.14 的 perls。

不要手动检查您是否在哈希中填充了一个插槽;如果它被undef用作数组引用,则会在此处自动创建数组引用。这被称为自动存活。当然,这需要您执行此取消引用(并跳过 的缩写形式push)。

在 Perl 中,parens排序优先级,并在用于赋值的 LHS 时创建列表上下文。他们创建数组。要创建匿名数组引用,请使用方括号:[$var]. 像你一样使用括号是没用的;$x = $y并且$y = ($y)是完全一样的。

所以你要么想要

push @{ $my_hash{$1} }, $2;

或者

if ($my_hash{$1}) {
  push $my_hash{$1}, $2;
} else {
  $my_hash{$1} = [$2];
}

编辑:我忽略了三件事。

如果glob在标量上下文中使用,它会变成一个迭代器。这通常是不需要的,除非以while(my $path = glob(...)) { ... }类似的方式使用。否则更难确保迭代器已用尽。相反,glob在列表上下文中使用以一次获取所有匹配项:my @paths = glob(...).

从哪里来$bdr_paths?里面是什么?

始终检查正则表达式是否实际匹配。这可以避免细微的错误,因为捕获$1等保持其价值直到下一次成功匹配。

于 2013-07-31T20:09:59.570 回答
1

当您说它$my_hash{$1} = ($2);在列表上下文中对其进行评估并将列表的最后一个对象存储在哈希中时。

my %h;
$h{a} = ('foo');
$h{b} = ['bar'];
$h{c} = ('foo', 'bar', 'bat'); # Will cause warning if 'use warnings;'
print Dumper(\%h);

$VAR1 = {
          'c' => 'bat',
          'b' => [
                   'bar'
                 ],
          'a' => 'foo'
        };

您可以看到它存储为值而不是数组引用。所以你可以存储一个匿名数组 ref$my_hash{$1} = [$2];然后你用push( @{ $my_hash{$1} }, $2);

于 2013-07-31T20:16:15.327 回答