为什么这个bash结构有效? (参数取代)

时间:2016-08-22 18:15:59

标签: bash

代码: ${non_existent_variable:+whatever} && echo "it works"

结果是it works。但为什么?部分之前&&计算为空字符串。但是尝试运行:&& echo test会出错。

我偶然尝试为bash创建三元运算符替换,其中set和unset变量的结果不同。它以这种方式工作,但我失去了它为什么会起作用。

PARAM=$(${tested_variable:+false} && echo var_exists || echo var_empty)

3 个答案:

答案 0 :(得分:6)

根据section 2.9.1 of the POSIX spec

  

A"简单命令"是一系列可选的变量赋值和重定向,按任意顺序,可选地后跟单词和重定向,由控制操作符终止。

第2.9.1节的最后一句是相关的一句:

  

如果存在命令名称,则执行将继续执行命令搜索和执行中所述。如果没有命令名,但命令包含命令替换,则命令应以完成的最后一个命令替换的退出状态完成。 否则,命令应以零退出状态完成。

因此,如果在所有扩展,重定向等之后,没有找到命令名称,则将其视为成功完成,退出状态为0。

但是,语法不允许在&&运算符之前使用空字符串。以下是语法错误:

&& echo it works

获得一个完全空的简单命令的唯一方法是使用非空字符串"蒸发"在扩张期间。实现这一目标的一种方法是使用不带引号的参数扩展来生成空字符串,这正是${non_existent_variable:+whatever}所做的。

答案 1 :(得分:2)

结果字符串并不重要,what the && construct is testing是之前语句的退出代码(即$?),而不是屏幕上回显的内容。因为参数扩展中没有错误(实际上,我不确定可能存在错误),语句会继续。

在评论中,你问为什么$(echo "") && echo test回应了一个值,这也是同样的原因。 echo语句退出0(即true),因此子shell也退出0,语句继续运行。

答案 2 :(得分:1)

${non_existent_variable:+whatever} && echo "it works"

作品(打印“有效”)因为 [1] 这是AND and OR lists

  

AND和OR列表是由&&和/或和||分别控制运营商。 AND和OR列表以左关联性执行。 AND列表的格式为

         command1 && command2
     当且仅当command1返回退出状态为零时才执行

命令。

即:command1的退出值为true的任何内容都会触发command2之后&&的执行。

这与此类型的代码完全相同:

true && echo "it works"

这也等同于:

: && echo "it works"

也与一样(即使变量未设置):

$ a=''
$ $a && echo "it works"

是的,变量扩展为null string,但其退出状态为零:
来自man bash

  

简单的命令扩展

     

如果在扩展后留下命令名称,则执行如下所述。 否则,该命令退出。如果其中一个扩展包含命令替换,则该命令的退出状态是执行的最后一个命令替换的退出状态。 如果没有命令替换,则命令退出状态为零

您可以通过以下方式查看退出状态:

$ a=''
$ $a; echo "$?"
0

即使之前有false的设置:

$ false; $a; echo "$?"
0

另请注意"$a"无效(并且在我测试的所有shell中也会失败):

$ "$a"
bash: : command not found

[1] 用bash语法回答,因为这个问题被标记为bash。但是上面解释的内容适用于我测试的所有外壳。