AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 423699
Accepted
Ole Tange
Ole Tange
Asked: 2018-02-13 12:55:01 +0800 CST2018-02-13 12:55:01 +0800 CST 2018-02-13 12:55:01 +0800 CST

Bash:设置状态的优雅方式?[关闭]

  • 772
关闭。这个问题需要细节或清晰。它目前不接受答案。

想改进这个问题?通过编辑此帖子添加详细信息并澄清问题。

4年前关闭。

改进这个问题
  • 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)来模拟条件。

bash exit-status
  • 4 4 个回答
  • 5705 Views

4 个回答

  • Voted
  1. ilkkachu
    2018-02-13T13:33:28+08:002018-02-13T13:33:28+08:00

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

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

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

    • 13
  2. Best Answer
    Kusalananda
    2018-02-13T13:19:35+08:002018-02-13T13:19:35+08:00

    使用以指定值退出的子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
    

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


    现在向问题添加了进一步的背景。

    我对分叉子外壳问题的看法是,像 GNU 这样configure的脚本一直都在这样做,而且除非在一个非常紧凑(长时间运行)的循环中完成,否则它不会非常慢。

    关于在 GNU 中/与 GNU 中的使用,我不能说太多,parallel因为我不是该软件的频繁用户。

    • 8
  3. Ole Tange
    2018-02-13T12:58:26+08:002018-02-13T12:58:26+08:00

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

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

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

    • 5
  4. Sergiy Kolodyazhnyy
    2018-02-13T14:22:38+08:002018-02-13T14:22:38+08:00

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

    • 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(){ [ "${1-0}" -eq 0 ] || return "$1" ; echo "foo"; }
    $ thing
    foo
    $ thing 0
    foo
    $ thing 1
    $ echo $?
    1
    $ thing 2
    $ echo $?
    2
    

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

    • 4

相关问题

  • 通过命令的标准输出以编程方式导出环境变量[重复]

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve