Bash:设置状态的优雅方式?

Bash:设置状态的优雅方式?
  • 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  

拘萨罗南达的版本可能是最好的。很清楚发生了什么。写起来并不长而且麻烦。它易于记忆且便于携带。唯一的缺点是它分叉了另一个 shell(花费约 0.5 毫秒):

$ parallel '(exit {= $_%=3 =}) || echo $?' ::: 0 1 2 3  

另一种情况是当您想要模拟错误情况时。比如说,如果您有一个长时间运行的程序,它设置了不同的退出代码,并且您正在编写一些将对不同退出代码做出反应的代码。您可以使用(exit $a)它来模拟条件,而不必运行长时间运行的程序。

答案1

好吧,return在一个函数中工作,所以让我们做一个:

$ ret() { return "${1-0}"; }
$ ret 1 || echo foo
foo
$ ret 123 ; echo $?
123

它比子 shell 需要更多的设置,但之后使用时间更短,并且不需要分叉子 shell。

答案2

使用以指定值退出的子 shell。

这将输出5

a=5; ( exit $a ) && echo foo; echo $?

这将输出fooand 0(注意,这个零是通过echo后续设置的,而不是通过exit子 shell 中的 来设置的):

a=0; ( exit $a ) && echo foo; echo $?

在您的缩写形式中(没有明显设置a$?明确调查):

( exit $a ) && echo foo

我的答案是,只是从表面上看待这个问题,并将其作为一个有趣的测验来解决,“我们如何设置$?(使用方便的符号)”。在这种情况下,我不会试图寻找任何更深层的含义、功能甚至背景(因为没有给出)。我也不判断解决方案的有效性、效率或可用性。有时,在我的回答中,我会说“......但不要那样做,因为......”,然后说“相反,这样做......”。在这种情况下,我选择将问题解释为一个简单的好奇测验。


现在向该问题添加了更多背景信息。

我对分叉子 shell 问题的看法是,像 GNU 这样的脚本configure会这样做每时每刻,并且除非在非常紧密(长时间运行)的循环中完成,否则它并不是非常慢。

我不能过多谈论 GNU 中 GNU 的使用,parallel因为我不是该软件的频繁用户。

答案3

一种选择(可能更快,但并不是更优雅):

test "$a" -eq 0 && echo foo

它执行echo但没有将退出值设置为$a,因此它是一个平庸的解决方案。

答案4

让我们检查一下您的假设:

  • true && echo foo将打印 foo.正确,因为&&遵循短路逻辑 AND;由于&&||运算符中的左关联性,如果最左边的命令返回成功退出状态 0 (总是true如此),则该运算符的最右边的命令将运行。

  • false && echo foo不会打印 foo.与上面解释的情况正好相反。

  • bash -c "exit $a" && echo foo将打印 foo 取决于$a.本质上是错误的$a控制假设&&。因为 && 是 AND 逻辑,所以它仅识别两种状态 - 成功或失败,其中失败是大于 0 的任何退出状态。因此exit 1andexit 2和- 全部与;exit 3无关。&&失败就是失败,无论$a价值如何;这就是为什么echo foo不运行。

因此答案是不,没有更优雅的方式无论如何,做一些在错误假设下运作的事情。但是,如果您的目的是通过命令设置退出状态,那么使用 Kusalananda 的答案所建议的内容就足够了 - 子 shell。我个人认为这与bash -c部分没有任何不同,除了子 shell 可以实现为子进程/分叉进程而不是单独的进程;还是不理想。请注意,$?用户也不应该通过变量设置 - 它旨在用于传达成功或失败的命令。

$a让我们暂时转移焦点。如果可以直接查的话为什么要设置$?and呢?将价值放置在它不属于的地方是没有意义的,即放置在 中。我建议将焦点从“优雅”(无论这意味着什么)转移到“逻辑”和“工作”。echo foo$a$a$?


好吧,让我们玩你的游戏吧。从中得到一点启发伊尔卡丘的回答。然而,这种方法消除了强制回显条件执行的需要。仅当它提供的变量指示成功时,它才会进行回显,并return阻止其执行。

$ thing(){ [ "${1-0}" -eq 0 ] || return "$1" ; echo "foo"; }
$ thing
foo
$ thing 0
foo
$ thing 1
$ echo $?
1
$ thing 2
$ echo $?
2

可能不明显的是你可以做thing $a

相关内容