Why is it that simply changing from enclosing my one-liner with
$ echo "puke|1|2|3|puke2" | perl -lne 'chomp;@a=split(/\|/,$_);print $a;'
$ echo "puke|1|2|3|puke2" | perl -lne "chomp;@a=split(/\|/,$_);print $a;"
$ perl -v
This is perl, v5.10.1 (*) built for x86_64-linux-thread-multi
With double quotes you are letting the parent shell interpolate variables first.
As you can check,
$a are unset in the subshell forked for this command by the parent shell. See a comment on
So the double-quoted version is effectively
echo "puke|1|2|3|puke2" | perl -lne 'chomp;@a=split(/\|/);print ;'
what prints the arrayref
A comment on the effects of having
$_ exposed to Bash. Thanks to Borodin for bringing this up.
$_ 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 $_
which prints an empty line. The reason may be that the
_ environment variable just isn't set for a subshell, as it is not invoked but
clone-ed, but I don't see this as an adequate explanation.
In any case,
$_ in the given pipeline isn't set.
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
zsh the last part of pipeline runs in the main shell, not a subshell, so
$_ is there.