了解推送到哈希和|| = []构造。 (在样板中生成.t)

时间:2011-11-21 14:14:55

标签: perl operators hashtable

我正在重新熟悉Perl,并且刚刚使用module-starter来初始化一个新项目。我现在正试图理解生成的代码。除了指示的后续行之外,一切都很好:

sub not_in_file_ok {
  my ($filename, %regex) = @_;
  open( my $fh, '<', $filename )
    or die "couldn't open $filename for reading: $!";

  my %violated;

  while (my $line = <$fh>) {
    while (my ($desc, $regex) = each %regex) {
        if ($line =~ $regex) {
            ##I'm having problems here
            push @{$violated{$desc}||=[]}, $.;
        }
    }
  }
  ...
}

我有两个问题:

  1. ||=[]。此|后跟|=,或者是||后跟=[]。有人能跟我说说这里发生的事吗? (我猜测“如果散列是空的,则创建一个空的匿名数组来初始化散列”,但我很难看到它是如何从代码中形成的。)
  2. push @{$violated{$desc}}, $.我理解这是指“为密码$desc分配行号%violated。但是从我读过的代码中,”查找密钥的值{ {1}} desc$violated{$desc}部分)的{1}},然后使用此值作为数组的符号引用($violated{$desc}部分),然后将行号推送到该数组“我不知道如何调和这两种观点。
  3. 我认为在这一行代码中我有很多东西需要学习 - 有人可以通过它来帮助我吗?

2 个答案:

答案 0 :(得分:8)

  • ||=:这是赋值运算符。实施例

    $a ||= $b;
    # corresponds to
    $a = $a || $b;
    

    请参阅man perlop。在你的例子中

    $a ||= [];
    # corresponds to
    $a = $a || [];
    

    即:如果将左操作数定义为空,否则分配空数组引用

  • %violated包含每个值的数组引用。你可以这样看:

    my $array_ref = $violated{$desc};
    push @{array_ref}, $.;
    

写得更详细:

  if (! $violated{$desc} ) {
      $violated{$desc} = [];
  }
  my $array_ref = $violated{$desc};
  push @{ $array_ref }, $.;

修改

数组和数组引用

  • 使用()构造的数组,包含动态有序的元素列表(在Perl数组中可以动态增长)

  • 数组引用是对数组的引用(或多或少是没有指针运算的指针)。您可以使用[]

  • 创建和数组引用

实施例

my @a = ( 1, 2, 3);
# $a[0] will contain 1

my $array_ref = [ 10, 11, 12 ];
# array_ref is a _pointer_ to an array containing 10, 11 and 12

要访问数组引用,您需要取消引用它:

@{ $array_ref };

my @array = @{ $array_ref }; # is valid

您可以作为数组

访问{ $array_ref}
${ $array_ref }[0]

现在回到评论中的问题:%violated是一个包含以下键值对的哈希:字符串($ desc)和数组引用

答案 1 :(得分:3)

让我们一步一步地解构这个问题:

  1. 该行用于填充arrayrefs的散列,其中arrayrefs包含$desc正则表达式匹配的行号。结果%violated哈希看起来像:

    ( desc1 => [ 1, 5, 7, 10 ], desc2 => [ 2, 3, 4, 6, 8 ] );

  2. push将数组作为其第一个参数。变量$violated{$desc是一个arrayref,而不是一个数组,因此@{...}用于取消引用它(取消引用与引用相反)。

  3. 现在是棘手的部分。大括号内的内容只是一种奇特的说法,如果$violated{$desc}中没有定义%violated(使用||进行测试),则会将其分配(=) empty arrayref([])。将其视为一行中的两项任务:

    $violated{$desc} = $violated{$desc} || [];

    push @{$violated{$desc}}, $.;

  4. 请注意,由于一个名为autovivification的功能,通常不需要这种复杂功能,它会在哈希中使用预期的上下文(在本例中为arrayref)自动创建以前未定义的键。我能想到的唯一情况是$violated{$desc} == 0之前的情况。