Why is it that simply changing from enclosing my one-liner with '
instead of "
affects the behavior of the code? The first line of code produces what is expected and the second line of code gives (to me!) an unexpected result, printing out an unexpected array reference.
$ echo "puke|1|2|3|puke2" | perl -lne 'chomp;@a=split(/\|/,$_);print $a[4];'
puke2
$ echo "puke|1|2|3|puke2" | perl -lne "chomp;@a=split(/\|/,$_);print $a[4];"
This is the Perl version:
$ perl -v
This is perl, v5.10.1 (*) built for x86_64-linux-thread-multi
ARRAY(0x1f79b98)
With double quotes you are letting the shell interpolate variables first.
As you can check, $_
and $a
are unset in the subshell forked for pipe by the parent shell. See a comment on $_
below.
So the double-quoted version is effectively
echo "puke|1|2|3|puke2" | perl -lne 'chomp;@a=split(/\|/);print [4];'
what prints the arrayref [4]
.
A comment on the effects of having $_
exposed to Bash. Thanks to Borodin for bringing this up.
The $_
is one of a handful of special shell parameters in Bash. It contains the last argument of the previous command, or the pathname of what invoked the shell or commands (via _
environment variable). See the link for a full description.
However, here it is being interpreted in a subshell forked to run the perl
command, its first. Apparently it is not even set, as seen with
echo hi; echo hi | echo $_
which prints an empty line (after first hi
). The reason may be that the _
environment variable just isn't set for a subshell for a pipe, but I don't see why this would be the case. For example,
echo hi; (echo $_)
prints two lines with hi
even though ( )
starts a subshell.
In any case, $_
in the given pipeline isn't set.
The split
part is then split(/\|/)
, so via default split(/\|/, $_)
-- with nothing to split. With -w
added this indeed prints a warning for use of uninitialized $_
.
Note that this behavior depends on the shell. The tcsh
won't run this with double quotes at all. In ksh
and zsh
the last part of pipeline runs in the main shell, not a subshell, so $_
is there.