phk*_*phk 11 shell posix command-substitution assignment exit-status
请参阅以下示例及其在 POSIX shell 中的输出:
false;echo $?或false || echo 1:1false;foo="bar";echo $?或foo="bar" && echo 0:0foo=$(false);echo $?或foo=$(false) || echo 1:1foo=$(true);echo $?或foo=$(true) && echo 0:0正如/sf/ask/478414121/ 上投票最高的答案所提到的:
$?用于查找上次执行命令的返回值。
在这种情况下,这可能有点误导,所以让我们获取 POSIX 定义,该定义也在该线程的帖子中引用:
? 扩展到最近管道的十进制退出状态(请参阅管道)。
所以看起来好像一个赋值本身算作一个命令(或者更确切地说是一个管道部分),它的退出值为零,但它应用在赋值的右侧之前(例如,我的示例中的命令替换调用)。
从实际的角度来看,我看到这种行为是有道理的,但对我来说,作业本身按该顺序计数似乎有些不寻常。也许为了让我更清楚为什么这对我来说很奇怪,让我们假设赋值是一个函数:
ASSIGNMENT( VARIABLE, VALUE )
Run Code Online (Sandbox Code Playgroud)
那么foo="bar"将是
ASSIGNMENT( "foo", "bar" )
Run Code Online (Sandbox Code Playgroud)
并且foo=$(false)会像
ASSIGNMENT( "foo", EXECUTE( "false" ) )
Run Code Online (Sandbox Code Playgroud)
这意味着首先EXECUTE运行,然后才运行,但它仍然是这里重要的状态。 ASSIGNMENTEXECUTE
我的评估是正确的还是我误解/遗漏了什么?这些是我将这种行为视为“奇怪”的正确理由吗?
ica*_*rus 10
任务的退出状态很奇怪。赋值失败最明显的方式是如果目标变量被标记为readonly。
$ err(){ echo error ; return ${1:-1} ; }
$ PS1='$? $ '
0 $ err 42
error
42 $ A=$(err 12)
12 $ if A=$(err 9) ; then echo wrong ; else E=$? ; echo "E=$E ?=$?" ; fi
E=9 ?=0
0 $ readonly A
0 $ if A=$(err 10) ; then echo wrong ; else E=$? ; echo "E=$E ?=$?" ; fi
A: is read only
1 $
Run Code Online (Sandbox Code Playgroud)
请注意, if 语句的 true 和 false 路径都没有被采用,赋值失败会停止整个语句的执行。如果分配失败,POSIX 模式下的 bash 以及 ksh93 和 zsh 都将中止脚本。
引用POSIX 标准:
没有命令名称但包含命令替换的命令具有 shell 执行的最后一个命令替换的退出状态。
这正是 shell 语法中涉及的部分
foo=$(err 42)
Run Code Online (Sandbox Code Playgroud)
它来自simple_command(simple_command ? cmd_prefix ? ASSIGNMENT_WORD)。因此,如果赋值成功,则退出状态为零,除非涉及命令替换,在这种情况下,退出状态是最后一个的状态。如果分配失败,则退出状态非零,但您可能无法捕捉到它。