如何在BEGIN块之外正确声明哈希?

时间:2012-10-29 21:44:15

标签: perl

考虑这个简单的程序。你能解释为什么在取消注释前两行之后输出会有所不同吗?我的哈希use strict发生了什么?如何修复程序以使用use strict

echo -e "key1\nkey2\nkey3" | perl -lne '
  #use strict; use warnings;
  #my %hash;
  BEGIN { 
    $hash{'key3'} = "value";
  }   
  chomp;
  if ($hash{$_}) {
    print "$_ matched";
  } else {
    print "$_ unmatched ";
  }
'

输出:

key1 unmatched 
key2 unmatched 
key3 matched

2 个答案:

答案 0 :(得分:5)

perl -ln包装代码,以便您最终获得

BEGIN { $/ = "\n"; $\ = "\n"; }
LINE: while (<>) {
    chomp;
    use strict; use warnings;
    my %hash;
    BEGIN { $hash{key3} = "value"; }
    ...
}

请注意如何为每一行创建新的%hash?如果您想使用use strict;,则需要使用包变量。

perl -lne'
    use strict; use warnings;
    our %hash;
    BEGIN { $hash{key3} = "value"; }
    ...
'

否则,您必须放弃-n

perl -le'
    use strict; use warnings;
    my %hash = ( key3 => "value" );
    while (<>) {
        chomp;
        ...
    }
'

PS - 您可能已经注意到,chomp使用-l-n时,{{1}}无效。

答案 1 :(得分:4)

使用-n开关隐含地将整个程序放在while (defined($_=<ARGV>)) { ...块中,包括my %hash声明:

perl -MO=Deparse -lne '
  use strict; use warnings; my %hash;
  BEGIN {
    $hash{'key3'} = "value";
  }
  chomp;
  if ($hash{$_}) {
    print "$_ matched";
  } else {
    print "$_ unmatched ";
  }
'

BEGIN { $/ = "\n"; $\ = "\n"; }
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    use warnings;
    use strict 'refs';
    my %hash;
    sub BEGIN {
        $hash{'key3'} = 'value';
    }
    &BEGIN;
    chomp $_;
    if ($hash{$_}) {
        print "$_ matched";
    }
    else {
        print "$_ unmatched ";
    }
}
-e syntax OK

也就是说,my %hash在循环的每次迭代中被重新声明。为了保持这种单行并且不会使其过于繁琐,请考虑声明our %hash使%hash成为包变量。