Answers:
(在POSIX中)在 Open Group基本规范的2.9.1节简单命令中对此进行了说明。那里有一堵墙。我请您注意最后一段:
如果有命令名称,则应按照“ 命令搜索和执行”中的描述继续执行。如果没有命令名称,但是命令包含命令替换,则命令应以最后执行的命令替换的退出状态完成。否则,该命令应以零退出状态完成。
因此,例如
Command Exit Status
$ FOO=BAR 0 (but see also the note from icarus, below)
$ FOO=$(bar) Exit status from "bar"
$ FOO=$(bar) baz Exit status from "baz"
$ foo $(bar) Exit status from "foo"
bash也是如此。但是,另请参见最后的“不太简单”部分。
phk,在他的问题中分配类似于具有退出状态的命令,除了有命令替换时?,建议
…似乎分配本身算作一条命令…出口值为零,但适用于该分配的右侧(例如,命令替换调用…)
这不是一个糟糕的方法。用于确定一个简单的命令的返回状态的粗方案(一个不含有;
,&
,|
,&&
或||
)为:
$(…)
-获取该命令的退出状态。该行的返回状态是您遇到的最后一个号码。
命令替换作为命令的参数,例如,foo $(bar)
不计算在内;您将从中获得退出状态foo
。释义phk的符号,这里的行为是
temporary_variable = EXECUTE( "bar" )
overall_exit_status = EXECUTE( "foo", temporary_variable )
但这有点过分简化。的整体退货状态
A = $(cmd 1)B = $(cmd 2)C = $(cmd 3)D = $(cmd 4)E = mc 2是的退出状态。在之后出现的分配分配不会整体退出状态设置为0。
cmd4
E=
D=
icarus在回答phk问题时提出了一个重要观点:变量可以设置为只读。POSIX标准第2.9.1节的倒数第二段说:
如果任何变量赋值试图给在当前shell环境中设置了只读属性的变量赋值(无论是否在该环境中进行赋值),都会发生变量赋值错误。有关这些错误的后果,请参阅Shell错误的后果。
所以如果你说
readonly A
C=Garfield A=Felix T=Tigger
返回状态为1。是否将字符串Garfield
,Felix
和/或Tigger
替换为命令替换无关紧要,但是请参阅下面的说明。
2.8.1节“ Shell错误的后果”还有另外一堆文本和一个表格,并以
在表中所示的所有情况下,都要求不退出交互式外壳,外壳不得对发生错误的命令进行任何进一步处理。
一些细节是有道理的;有些不:
A=
分配有时会中止命令行。在上面的示例中,C
将设置为Garfield
,但未T
设置(当然也不设置 A
)。C=$(cmd1) A=$(cmd2) T=$(cmd3)
cmd1
cmd3
cmd2
在我的bash版本中,
只读A C = 某物 A = 某物 T = 某物 cmd 0
确实执行。特别是,cmd0
C = $(cmd 1)A = $(cmd 2)T = $(cmd 3) cmd 0执行 和,但不会。(请注意,这与没有命令时的行为相反。)并且它在的环境中进行设置(以及)。我不知道这是否是bash中的错误。
cmd1
cmd3
cmd2
T
C
cmd0
该答案的第一段涉及“简单命令”。 规范说,
“简单命令”是一系列可选变量分配和重定向,可以按任意顺序进行,并可选地后面跟单词和重定向,并由控制运算符终止。
这些语句类似于我的第一个示例块中的语句:
$ FOO=BAR
$ FOO=$(bar)
$ FOO=$(bar) baz
$ foo $(bar)
前三个变量包括变量分配,后三个变量包括命令替换。
但是某些变量分配并不是那么简单。 bash(1)说,
赋值语句也可能出现作为参数传递给
alias
,declare
,typeset
,export
,readonly
,和local
内置命令(声明命令)。
对于export
,POSIX规范说,
退出状态
0
所有名称操作数均已成功导出。
> 0至少一个名称无法导出,或者
-p
指定了选项并发生错误。
POSIX不支持local
,但是bash(1)表示,
local
当不在函数内时使用是错误的。除非local
在函数外部使用,返回的名称无效或name是只读变量,否则返回状态为0 。
阅读两行之间,我们可以看到声明命令,例如
export FOO=$(bar)
和
local FOO=$(bar)
更像
foo $(bar)
只要他们忽略退出状态bar
,并给您基于主命令的退出状态(export
,local
,或foo
)。所以我们有像
Command Exit Status
$ FOO=$(bar) Exit status from "bar"
(unless FOO is readonly)
$ export FOO=$(bar) 0 (unless FOO is readonly,
or other error from “export”)
$ local FOO=$(bar) 0 (unless FOO is readonly,
statement is not in a function,
or other error from “local”)
我们可以证明的
$ export FRIDAY=$(date -d tomorrow)
$ echo "FRIDAY = $FRIDAY, status = $?"
FRIDAY = Fri, May 04, 2018 8:58:30 PM, status = 0
$ export SATURDAY=$(date -d "day after tomorrow")
date: invalid date ‘day after tomorrow’
$ echo "SATURDAY = $SATURDAY, status = $?"
SATURDAY = , status = 0
和
myfunc() {
local x=$(echo "Foo"; true); echo "x = $x -> $?"
local y=$(echo "Bar"; false); echo "y = $y -> $?"
echo -n "BUT! "
local z; z=$(echo "Baz"; false); echo "z = $z -> $?"
}
$ myfunc
x = Foo -> 0
y = Bar -> 0
BUT! z = Baz -> 1
幸运的是ShellCheck捕获了错误并提出了SC2155,该建议
export foo="$(mycmd)"
应该更改为
foo=$(mycmd)
export foo
和
local foo="$(mycmd)"
应该更改为
local foo
foo=$(mycmd)
FOO=$(bar)
),值得注意的是,理论上退出状态和分配都可能起作用,请参见unix.stackexchange.com/a/341013/117599
A=foo cmd
它cmd
也会运行A
吗?
A
为只读,则命令C=value₁ A=value₂ T=value₃
设置C
但未设置T
(当然A
也未设置)-外壳程序终止处理命令行,忽略T=value₃
,因为这A=value₂
是错误。(2)感谢您对“ 堆栈溢出”问题的链接-我已经发布了有关它的评论。
local=$(false)
有出口值0
,因为(从该名男子页): It is an error to use local when not within a function. The return status is 0 unless local is used outside a function, an invalid name is supplied, or name is a readonly variable.
。对于以这种方式设计的天才来说,这还不够。
local
与此有什么联系吗?例如local foo=$(bar)
?