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

I am working on a perl one-liner to print the second column of every line in a file.

The data is like this:
< 0170 < 0206 < 0216 < 0223
When I run: perl -e 'while(<>) {print (split)[1]}' filename I get:
< 0170 < 0206 < 0216 < 0223
Which is not what I want. I can use a simple awk statement easily get just the second column, but I would prefer to use perl.
Thanks

Replies are listed 'Best First'.
Re: Yet Another Split Question
by blokhead (Monsignor) on Aug 11, 2004 at 23:22 UTC
    Your code gives me an error because
    print (split)[1];
    doesn't mean what you think it is. The compiler doesn't know whether you mean:
    ( print(split) )[1]; print( (split)[1] );
    It's kinda like the expression: print (5 + 3) * 4 prints 8, and has a return value of 4 because it's parsed as: ( print(5 + 3) ) * 4. But in your case, since a list slice needs parentheses around the entire list your code causes a compile error (there are not parentheses around print(split)).

    You can disambiguate those parentheses with a unary plus, to tell the compiler that the parentheses aren't used for a function call, they just are used as a grouping in the first argument (and the function call is without parentheses).

    print +(split)[1];
    Or you could just explicitly parenthesize two levels as above.

    Update: not relevant to your specific question, but to your code in general -- you can just replace what you have with:

    perl -lnae 'print $F[1]' somefile
    -a does auto split into @F, -n does auto while(<>){..}, and -l does auto newline on print statements. See perlrun for details.

    blokhead

      And here we have another fine example of the need for a whitespace dependency in the parsing of parentheses. Which is why the OP's code above will work correctly in Perl 6.
        It's certainly a common enough error to warrant a warning (which, unsurprisingly, perl5 does give once the syntax error-producing [] is removed). But it's a only a warning, so that people with a whitespacy coding style can turn it off.
Re: Yet Another Split Question
by graff (Chancellor) on Aug 12, 2004 at 01:06 UTC
    I'd normally do this sort of thing thusly:
    perl -pale '$_=$F[1]'
    • -p : enclose the script in while (<>) { ... } continue { print }
    • -a : prepend  @F = split (within the loop)
    • -l : strip "\n" (actually, $/) on input, put it back on output
    • -e : treat the next arg as the script to be run, within the above conditions.

    (update: forgot to mention, in case you didn't know: perldoc perlrun )

    (another update: if you're using a Bourne-style shell -- bash, korn, zsh, etc -- you could add something like this to your shell's "rc" file:

    pcol() { perl -pale "\$_=\$F[$1]" $2 }
    This defines a shell function that can be used as follows:
    pcol 1 list.file # prints $F[1] (second column) from list.file ls -lg | pcol 4 # prints byte counts of files in cwd
    Have fun...)