in reply to Re: $_ and filehandles
in thread $_ and filehandles

This node falls below the community's threshold of quality. You may see it by logging in.

Replies are listed 'Best First'.
Re^3: $_ and filehandles
by Anonymous Monk on Aug 28, 2005 at 21:38 UTC
    Again, with the "doesn't work." Please attach a sample small program and sample input data set that illustrates the problem. For example, the following works fine for me:
    my (@a,@b); ($a[$#a+1],$b[$#b+1]) = split /;/ while <>; print "@a\n"; print "@b\n";
    Sample data:
    1;2 3;4 5;6 7;8
    Sample output:
    1 3 5 7 2 4 6 8
    @b's output looks funny because you have un-chomped newlines in all the @b values.
      Here's the data:
      3 3453434 1;1125070863 2;1125074577 4;1125346343
      Here's the effective code:
      my (undef, $salt, @post, @time) = (<FILE>, <FILE>, (), ()); ($post[$#post + 1], $time[$#time + 1]) = split(/;/) while (<FILE>); print "@post\n@time\n";
      Output:
      1;1125070863 2;1125074577 4;1125346343
      What it should be: (pretend that it was chomped)
      1 2 4 1125070863 1125074577 1125346343

        I think your misunder standing was that you belived that the items on the right hand side of the = coresponded with the items on the left hand side. In Perl if the left hand side looks like a list or an array (any time there is an array or parentheses) all arguments on the right hand side are flatend into a single list, and asigned to the left hand side from left to right with a scalar (or undef) consuming one item, and the first array or hash consuming all remaining items.

        my (undef, $salt, @post, @time) = (<FILE>, <FILE>, (), ());

        So on this line your using <FILE> in array context, the entire contents of the file will be read in and returned as a list. Then the first line is discarded, the second line placed in $salt and the rest of the lines in @post, because @post consumes all the lines there is no data to place in @time so @time is left empty. After that point there is no more data to read so your while loop's conditional evaluates to false on the first test and the split is never executed. The print statment displays the 3 lines contained in @post as would be expected.

        A solution would be to not give the first 2 uses of <FILE> array context, either by directly asigning to a scalar, or by forcing scalar context with the scalar() function.

        <FILE>; #discard a line (one line is read in void context) my $salt = <FILE>; #provide scalar context so only one line is read my (@post, @time); ($post[$#post + 1], $time[$#time + 1]) = split(/;/) while (<FILE>); print "@post\n@time\n";
        my (undef, $salt, @post, @time) = (scalar(<FILE>), scalar(<FILE>)); #f +orce scalar context. ($post[$#post + 1], $time[$#time + 1]) = split(/;/) while (<FILE>); print "@post\n@time\n";

        I find the first better as long as you comment that you want to discard the line when <FILE> is on a line by it self.