in reply to Perl : Split/Regex

Use split to split your $result on whitespace, and push to the right array depending on whether you're seeing a "Y":

foreach my $result (@result) { my @fields = split /\s+/, $result; if($fields[3] // "" eq "Y") { push @streams, $fields[0]; } else { push @spaces, $fields[0]; } }

A note on the // "" bit: $fields[3] may be undefined if your $result didn't have enough fields, so I'm using the defined-or operator there to avoid spurious warnings ("Use of uninitialized value $fields[3] in string eq at 1099476.pl line 21").

Replies are listed 'Best First'.
Re^2: Perl : Split/Regex
by johngg (Canon) on Sep 03, 2014 at 23:01 UTC

    Since the OP mentions that the "Y" will be at the end, why not use a [ -1 ] subscript to avoid the "defined" complication? You could also use a single push with the conditional and target arrays in a ternary. Some may find this less readable than the if ... else ... but I prefer it for simple "push to this or that depending" situations.

    $ perl -Mstrict -Mwarnings -E ' open my $inFH, q{<}, \ <<EOD or die $!; ws.abc.dsfsfsfwerfrwef std 13232 ws.dfsdferferfregregrgr std 99868 Y ws.abc.asddwefewfewfewf std 45345 fwfrwfrefergegregerefds std 36754 Y ws.abc.fferfergregrfreg std 45435 EOD my @streams; my @spaces; while ( <$inFH> ) { my @flds = split; push @{ $flds[ -1 ] eq q{Y} ? \ @streams : \ @spaces }, $flds[ 0 ]; } say qq{@streams}; say qq{@spaces};' ws.dfsdferferfregregrgr fwfrwfrefergegregerefds ws.abc.dsfsfsfwerfrwef ws.abc.asddwefewfewfewf ws.abc.fferfergregrfreg $

    I hope this is of interest.

    Cheers,

    JohnGG

      Since the OP mentions that the "Y" will be at the end, why not use a [ -1 ] subscript to avoid the "defined" complication?

      That works, but what if you just so happen to have a "Y" in the third field? The OP's example lines only have numbers, granted, but I didn't want to assume too much about how his/her data is structured.

      You could also use a single push with the conditional and target arrays in a ternary. Some may find this less readable than the if ... else ... but I prefer it for simple "push to this or that depending" situations.

      Ah, yes, that's a good point. I was trying that, actually; it didn't work ("Not an ARRAY reference at ..."), but it didn't occur to me to wrap the whole shebang in a @{ }. OTOH, between that and the need to take references to the arrays you want to push to, it is indeed on the cryptic side.

      Nevertheless, I learned something new. Thank you for enlightening me, brother!

        ..That works, but what if you just so happen to have a "Y" in the third field?..

        For the lines without the Y there would be no *fourth field counting from 0, check or count it.
        And even if you decide to include Y in the those lines last field if($fields[-1] eq 'Y'){.. would still work.


        *Updated this in light of the discuss that follows! Which has nothing to do with the level of correctness as some may presume.
        If you tell me, I'll forget.
        If you show me, I'll remember.
        if you involve me, I'll understand.
        --- Author unknown to me

      The push reads better without the obfuscating ref/deref stuff:

      push (($flds[-1] eq 'Y' ? @streams : @spaces), $flds[0]);

      Update: Ok, so that was a fail - struck

      Perl is the programming world's equivalent of English

        Reads better perhaps, but doesn't actually work. First argument to push must be something starting with the  @ sigil or, with Perl 5.14+, a reference to an unblessed array.

        c:\@Work\Perl>perl -wMstrict -le "print $]; ;; my (@streams, @spaces); my $y = 'Y'; push (($y eq 'Y' ? @streams : @spaces), 'Z'); print qq{(@streams) (@spaces)}; " 5.014004 Not an ARRAY reference at -e line 1. c:\@Work\Perl>perl -wMstrict -le "print $]; ;; my (@streams, @spaces); my $y = 'Y'; push (($y eq 'Y' ? \@streams : \@spaces), 'Z'); print qq{(@streams) (@spaces)}; " 5.014004 (Z) ()