2

Consider this simple program. Can you explain why the output is different after uncommenting the first two lines? What is happening with my hash with use strict? How to fix the program to work with 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 ";
  }
'

Output:

key1 unmatched 
key2 unmatched 
key3 matched
4

2 回答 2

5

perl -ln wraps the code so that you end up with

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

Notice how you create a new %hash for every line? If you wanted to use use strict;, you'd use a package variable.

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

Otherwise, you have to drop -n.

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

PS - As you may have noticed, it's useless to chomp when using both -l and -n.

于 2012-10-29T21:53:25.080 回答
4

Using the -n switch implictly puts your entire program inside a while (defined($_=<ARGV>)) { ... block, including your my %hash statement:

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

That is, my %hash is redeclared in each iteration of the loop. To keep this as a one-liner and without making it too cumbersome, consider declaring our %hash to make %hash a package variable.

于 2012-10-29T21:51:43.670 回答