为什么从 ' 更改为 " 会影响这种单行的行为?

sai*_*l0r 1 shell perl double-quotes single-quotes

为什么只是简单地将我的单行'改为而不是"影响代码的行为?第一行代码产生了预期的结果,第二行代码给出了(给我!)一个意想不到的结果,打印出一个意想不到的数组引用。

$ 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];"
Run Code Online (Sandbox Code Playgroud)

这是 Perl 版本:

$ perl -v

This is perl, v5.10.1 (*) built for x86_64-linux-thread-multi

ARRAY(0x1f79b98)
Run Code Online (Sandbox Code Playgroud)

zdi*_*dim 5

使用双引号,您首先让 shell 插入变量。

正如您可以检查的那样,$_并且$a在子外壳中未设置由父外壳分叉为管道。请参阅$_下面的评论。

所以双引号版本是有效的

echo "puke|1|2|3|puke2" | perl -lne 'chomp;@a=split(/\|/);print [4];'
Run Code Online (Sandbox Code Playgroud)

什么打印 arrayref [4]


关于$_接触 Bash的影响的评论。感谢Borodin提出这个问题。

$_是屈指可数的一个特殊的shell参数中的Bash。它包含上一个命令的最后一个参数,或者调用 shell 或命令的路径名(通过_环境变量)。有关完整说明,请参阅链接。

但是,在这里它在子shell 中被解释为分叉运行perl命令,它的第一个。显然它甚至没有设置,如所见

echo hi;  echo hi | echo $_
Run Code Online (Sandbox Code Playgroud)

打印一个空行(在 first 之后hi)。原因可能_是没有为管道的子外壳设置环境变量,但我不明白为什么会这样。例如,

echo hi; (echo $_)
Run Code Online (Sandbox Code Playgroud)

hi即使( )开始一个子shell ,也会打印两行。

在任何情况下,$_在给定的管道中都没有设置。

split然后该部分是split(/\|/),所以通过默认split(/\|/, $_)- 没有什么可以分割的。随着-w加入这个确实打印使用的未初始化的警告$_

请注意,此行为取决于外壳。该tcsh不会在所有双引号运行此。在kshzsh管道的最后一部分在主壳,而不是一个子shell中运行,所以$_是存在的。