in reply to Re: How can I group lines in a file?
in thread How can I group lines in a file?

Hi BrowserUk,

I like your solution but I'm not sure I understand it properly. Why does this line work?
/(\S+)\s+(\S+)/ and push @{ $HoA{ $1 } }, $2 while <$fh>;
I broke the line into 3 parts (split, push and the reading the file) and I understand what each part does but what I don't understand is why it worked.

For example, should I read the line from right to left? So, read the file then split "and" push??? Why does split and push combo work together. This is what I don't understand.

If you can explain it or point me to the proper documentation, I would really appreciate it. Thanks

Replies are listed 'Best First'.
Re^3: How can I group lines in a file?
by Anonymous Monk on May 17, 2009 at 04:31 UTC
    split is a function, so there is no split. That code is equivalent to
    while( <$fh> ){ if(/(\S+)\s+(\S+)/){ push @{ $HoA{ $1 } }, $2; } }
    to test, add before the if
    warn 'scalar ', /(\S+)\s+(\S+)/; warn 'list ', join '|', /(\S+)\s+(\S+)/;
      my mistake, it should be warn 'scalar ', scalar /(\S+)\s+(\S+)/;
      oops, my bad. When I was writing my own version, I used "split" to get the values which is basically the regex thing that BrowserUk did. Also, my version is similar to what you just wrote... Read the file, get the values, push it in a hash of array.

      But BrowserUk's version was done in a single line which I'm still perplexed. Why does it work? (regex thing "and" pushing it in a hash of array).

      How does "and" work? How can it get the regex values and push it to HoA? Thanks.
        Why does this line work? /(\S+)\s+(\S+)/ and push @{ $HoA{ $1 } }, $2 while <$fh>;

        The regex matches against $_ (which is set to each line in turn by the while), and sets $1 to the first whitespace delimited 'word', and $2 to the second.

        The and checks that the line matches, and if it does pushes the second 'word' onto an array within the hash keyed by the first word.

        You can also tighten the regex a tad and add some error checking:

        #! perl -slw use strict; use Data::Dump qw[ pp ]; my %HoA; open my $fh, '<', 'junk.dat' or die $!; /(\S+)\s+(\d+)/ and push @{ $HoA{ $1 } }, $2 or warn "Bad data '$_' at line $.\n" while <$fh>; close $fh; pp \%HoA; __END__ c:\test>junk Bad data 'the quick brown fox ' at line 5 { ernest => [38, 27], jim => [14, 34], john => [23, 44], matilda => [4 +3, 22] }

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.