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

What am doing wrong?
use strict; die "Usage: <file1> <file2>\n" unless @ARGV == 2; my $file_1 = $ARGV[0]; my $file_2 = $ARGV[1]; open (FILE2, $file_2) or die "Couldn't open file: $!"; while (<FILE2>) { if ($_ =~ s/^confederation-as-router\:\W+\d\W+\d+\W//) { push(my @file2, $_); #I can print the entire array here. open (FILE3, '>routers') or die "Couldn't open file: $!"; print FILE3 @file2; close FILE3;
When I read the contents of routers, it only contains one element of @file2

Replies are listed 'Best First'.
Re: Writing the contents of an array to a file
by Fastolfe (Vicar) on Sep 28, 2000 at 23:41 UTC
    push(my @file2, $_);
    Since you didn't post all of your code, I'm not 100% certain how you're doing your scoping, but I bet the my keyword there is why your @file2 is appearing empty or nearly so below. It will scope @file2 within that block (the if block, most likely).
    my @file2; # scope it OUTSIDE of your block while (<FILE2>) { if (s/.../.../) { push(@file2, $_); } } # end your while here?? # ... print FILE3, @file2; # prints all elements
RE: Writing the contents of an array to a file
by geektron (Curate) on Sep 28, 2000 at 23:42 UTC
    context has bitten me before.

    it's been suggested that to avoid context problems, use something like this:

    my $text = join(' ', @file2);

    then print $text to the file.

    i had a similar problem yesterday with a textarea in a CGI script i was writing yesterday. the join fixed it.

    UPDATE: the scoping is also a problem. i just looked again. @file2 should be declared outside of the block. try a use vars qw/ @file2 / or declare @file2 outside of the while loop.

    UPDATE 2: OK - the scoping was the issue, and  join is a bit of overkill. :)

      print invokes list context:
      [firewheel ~]$ perl my @list = (1 .. 4); print STDOUT @list;
      I prefer something like print STDOUT "@list";, which is semantically equivalent to print STDOUT (join($", @array));

      Fastolfe is correct, though. This is a scoping issue.

        FYI, $" is to print "@list" as $, is to print @list or print $a, $b, $c
        @a = qw{ one two }; @b = qw{ tre for }; { local $" = "-"; print "@a @b"; # one-two tre-for } { local $, = "-"; print @a, @b; # one-two-tre-for local $" = ":"; print "@a", "@b"; # one:two-tre:for }
        Cheers
      In this case, a join is unnecessary (but still perhaps valuable for others that need to do similar acts in the future):
      @a = (1, 2, 3); print @a; print $a[0], $a[1], $a[2]; # equivalent to @a
      Passing arguments to a function (even internal) as an array is just like passing a list of your own individual arguments. In this case, however, each element will be printed one after another. If you want to separate with spaces, either set $, or use join as you've done.

      If you're working from a list generated from a file, though, as we are here, newlines are still at the end of each element in the list, so printing them out like he's doing will have the desired effect:

      @list = <INPUT_FILE>; print OUTPUT_FILE @list; # exact (textual) copy