为什么从'变为'会影响这个单行的行为?

时间:2017-05-11 21:46:38

标签: perl shell 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];"

这是Perl版本:

$ perl -v

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

ARRAY(0x1f79b98)

2 个答案:

答案 0 :(得分:4)

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

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

所以双引号版本实际上是

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

打印arrayref [4]的内容。

评论让$_暴露给Bash的影响。感谢Borodin提出这个问题。

$_是Bash中少数special shell parameters之一。它包含上一个命令的最后一个参数,或者调用shell或命令的路径名(通过_环境变量)。请参阅链接以获取完整说明。

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

所示
echo hi;  echo hi | echo $_

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

echo hi; (echo $_)

使用hi打印两行,即使( )启动子shell。

在任何情况下,都不会设置给定管道中的$_

然后split部分为split(/\|/),因此默认为split(/\|/, $_) - 无需拆分。添加-w后,这确实会显示使用未初始化$_的警告。

请注意,此行为取决于shell。 tcsh根本不会使用双引号来运行它。在kshzsh中,管道的最后一部分在主shell中运行,而不是子shell,因此$_就在那里。

答案 1 :(得分:1)

这实际上是一个shell主题,而不是perl主题。

在shell中:

单引号保留它们包含的所有字符的文字值,包括$和反斜杠。但是,对于双引号,$,反引号和反斜杠字符具有特殊含义。

例如:

'\"'评估为\"

,而

"\'"评估为'

因为使用双引号,反斜杠作为转义字符具有特殊含义。