true && echo foo
将打印foo
。false && echo foo
不会打印foo
。bash -c "exit $a" && echo foo
将foo
根据$a
.
有没有更优雅的方式来写最后一个?仅仅为了设置退出值就必须启动一个 shell 似乎有点多。我在想类似的事情:
return $a && echo foo
exit $a && echo foo
exceptreturn
仅适用于函数,并且exit
永远echo foo
不会运行。
在这种情况下,优雅意味着:
- 容易理解
- 便携的
- 易于阅读
- 容易写
- 容易记住
- 短的
- 高性能
例如,如果true
将退出代码作为参数(这是一个文档化的特性),它会非常优雅。
那么有没有更优雅的方式呢?
背景
可以使用的地方之一是:
$ parallel 'setexitval {= $_%=3 =} || echo $?' ::: 0 1 2 3
Kusalananda 的版本可能是最好的。很清楚发生了什么。写起来不长也不麻烦。它易于记忆和便携。唯一的缺点是它分叉了另一个 shell(它的成本约为 0.5 毫秒):
$ parallel '(exit {= $_%=3 =}) || echo $?' ::: 0 1 2 3
另一种情况是当您想要模拟错误情况时。比如说,如果你有一个长时间运行的程序,它设置了不同的退出代码,并且你正在编写一些会对不同退出代码做出反应的东西。不必运行长时间运行的程序,您可以使用它(exit $a)
来模拟条件。
好吧,
return
在一个函数中工作,所以让我们做一个:它需要比子shell 更多的设置,但之后使用时间更短,并且不需要分叉子shell。
使用以指定值退出的子shell。
这将输出
5
:这将输出
foo
and0
(注意,这个零是通过echo
成功设置的,而不是由exit
子shell中的):以您的缩短形式(没有明显设置
a
或$?
明确调查):我的答案是从表面上看问题并将其作为一个好奇的测验来解决,“我们可以如何设置
$?
(使用方便的符号)”。在这种情况下,我没有尝试寻找任何更深层次的含义或功能甚至上下文(因为没有给出)。我也不判断解决方案的有效性、效率或可用性。我有时在我的回答中确实会说“......但不要那样做,因为......”,然后是“相反,这样做......”。在这种情况下,我选择将问题解释为只是一个好奇的测验。现在向问题添加了进一步的背景。
我对分叉子外壳问题的看法是,像 GNU 这样
configure
的脚本一直都在这样做,而且除非在一个非常紧凑(长时间运行)的循环中完成,否则它不会非常慢。关于在 GNU 中/与 GNU 中的使用,我不能说太多,
parallel
因为我不是该软件的频繁用户。一种选择(可能更快但不是更优雅):
它执行
echo
但没有将退出值设置为$a
,因此它是一个平庸的解决方案。让我们检查一下您的假设:
true && echo foo
将打印 foo。正确,因为&&
坚持与短路逻辑;由于&&
和||
运算符中的左关联性,如果最左边的命令返回成功退出状态 0(true
总是如此),则该运算符最右边的命令将运行。false && echo foo
不会打印 foo。与上面解释的情况正好相反。bash -c "exit $a" && echo foo
将打印 foo 取决于$a
. 本质上是错误的假设,即$a
控制&&
。因为&&
是 AND 逻辑,所以它只识别两种状态——成功或失败,其中失败是任何高于 0 的退出状态。因此exit 1
,andexit 2
和exit 3
- 都与 ; 无关&&
。失败就是失败,无论$a
价值如何;这就是为什么echo foo
不运行。因此答案是否定的,无论如何,没有更优雅的方式来做一些在错误假设下运行的事情。但是,如果您的目的是通过命令设置退出状态,则足以使用 Kusalananda 的回答所建议的 - 一个子外壳。我个人认为这与部分没有任何不同
bash -c
,除了子外壳可以实现为子进程/分叉进程而不是单独的进程;仍然不理想。请注意,$?
用户也不应通过变量设置 - 它旨在用于传达成功或失败的命令。让我们将注意力转移到
$a
一秒钟。为什么要设置$?
和echo foo
,如果可以直接检查$a
?$a
将值放在不属于它的地方是没有意义的,即在$?
. 我建议将焦点从“优雅”(无论这意味着什么)转移到“逻辑”和“工作”。好吧,但让我们玩你的游戏。从ilkkachu 的回答中获得适度的灵感。然而,这种方法消除了强制回显条件执行的需要。
return
如果仅当它提供的变量指示成功并阻止其执行时,它才会回显。可能不明显的是你可以做
thing $a