mpj196884 has asked for the wisdom of the Perl Monks concerning the following question:

Hello perlmonks

I'm hoping to make my first properly-marked post here. I'm trying to get basic things done in perl. I've written a script that separates comments from scriptures, but I don't seem to have figured out how to print it:

#!/usr/bin/perl # perl gg2.pl use warnings; use strict; my $filename3 = 'ot5.txt'; open(my $hh, '<', $filename3) or die "cannot open $filename3 for reading: $!"; # open output file my $filename2 = 'outfile16.txt'; open(my $gh, '>', $filename2) or die "cannot open $filename2 for writing: $!"; # open output file my $filename4 = 'outfile43.txt'; open(my $hg, '>', $filename4) or die "cannot open $filename4 for writing: $!"; my %Scripts; my %comments; local $/=""; while ( <$hh> ) { my @s = split /\s+/, $_; my $verse = $s[0]; my $counter = 0; if ($s[0] =~ m/^\d/) { my $verse = $s[0]; my $script = join(' ', @s[1..$#s]); $Scripts{$verse} = $script; print $gh $_; } else { $counter++; my $comment = join(' ', @s); $comments{$counter} = $comment; print $hg $_; } } foreach $verse (sort keys %Scripts) { print "$verse => $Scripts($verse)\n"; } # close input and output files close($hh) or die("Error closing $filename3: $!"); close($gh) or die("Error closing $filename2: $!"); close($hg) or die("Error closing $filename4: $!");

Perl.exe complains with the following: C:\MinGW\source>perl gg2.pl Global symbol "$verse" requires explicit package name at gg2.pl line 52. Global symbol "$verse" requires explicit package name at gg2.pl line 54. Global symbol "$Scripts" requires explicit package name at gg2.pl line 54. Global symbol "$verse" requires explicit package name at gg2.pl line 54. Execution of gg2.pl aborted due to compilation errors. C:\MinGW\source>

Fishing for tips,

Replies are listed 'Best First'.
Re: printing a hash
by perliff (Monk) on May 26, 2009 at 06:25 UTC
    The error is because you are declaring the variable $verse and inside the foreach loop. This cannot be seen outside. So declare it where you declare %Scripts etc. Also there is an error in your print statement. Here is the correct statement.

    print "$verse => $Scripts{$verse}\n";

    You need these "{}" instead of "()".

    perliff

    ----------------------

    "with perl on my side"

Re: printing a hash
by AnomalousMonk (Archbishop) on May 26, 2009 at 08:47 UTC
    Just to elaborate on perliff's reply, you also must declare  $verse as a my variable in the final  foreach loop (see Foreach Loops in perlsyn):

    foreach my $verse (sort keys %Scripts) { print "$verse => $Scripts{$verse}\n"; }
Re: printing a hash
by toolic (Bishop) on May 26, 2009 at 15:23 UTC
    You could also consider using the Data::Dumper core module. It is very handy in printing hashes, arrays and arbitrary Perl data structures:
    use Data::Dumper; print Dumper(\%Scripts);
Re: printing a hash
by GrandFather (Saint) on May 26, 2009 at 21:46 UTC

    Just to elaborate slightly on AnomalousMonk's reply:

    A few important sentences from Foreach Loops are:

    The foreach loop iterates over a normal list value and sets the variable VAR to be each element of the list in turn. If the variable is preceded with the keyword my, then it is lexically scoped, and is therefore visible only within the loop. Otherwise, the variable is implicitly local to the loop and regains its former value upon exiting the loop.

    There is a very important point here that is likely to go unnoticed: the for loop variable is an alias to each element of the list in turn. That means that if you change the content of the variable you change the element of the list it is aliased to. It also implies that when the loop exits the variable is no longer aliased to anything - loop variables don't retain their content outside the loop. Consider:

    use strict; use warnings; my $var = 3.141; my @array = (1 ..5); for $var (@array) { $var += 10; } print "\$var: $var\n"; print "\@array: @array\n";

    Prints:

    $var: 3.141 @array: 11 12 13 14 15

    True laziness is hard work