|| 之后的联合命令(或)运算符

|| 之后的联合命令(或)运算符

当我按照下面的方式编写代码时,我可以在语句后运行多个命令else

if [ "$?" -eq 0 ]
    then              
        echo "OK"
    else 
        echo "NOK"
        exit 1
fi

但是,当我使用另一种语法时,我无法在或者:

[ "$?" -eq 0 ] && echo "OK" || (echo "NOK" >&2 ; exit 1)

在我的用例中,我有一个基于 的复杂脚本"$?" == 0,因此我正在寻找一种在消息不正确时中止的方法(除了回显消息)。

答案1

这对( )生成一个子 shell,破坏了使用内部 exit 命令退出整个脚本的目标。

只需替换( ){ } (和调整后的语法,因为{ }不是自动分隔符,而是更像命令:后面的空格{和最后一个命令内部必须以一些终止符结尾:;适合):这将在同一个 shell 中运行命令链,从而退出会影响这个外壳。

[ "$?" -eq 0 ] && echo "OK" || { echo "NOK" >&2; exit 1;}

更新:@D.BenKnoble 评论说应该echo失败,行为不会像以前的if ...; then ... else ... fi构造一样。因此,第一个echo退出代码必须使用 noop:命令“转义”(内置命令不会失败)。

[ "$?" -eq 0 ] && { echo "OK"; :;} || { echo "NOK" >&2; exit 1;}

参考:

POSIX:

分组命令

分组命令的格式如下:

(compound-list)
     Execute compound-list in a subshell environment; see Shell
     Execution Environment. Variable assignments and built-in commands 
     that affect the environment shall not remain in effect
     after the list finishes.

[...]

{ compound-list;}
     Execute compound-list in the current process environment. The
     semicolon shown here is an example of a control operator delimiting
     the } reserved word. Other delimiters are possible, as shown
     in Shell Grammar; a <newline> is frequently used.

破折号联机帮助页,bash 联机帮助页,...

答案2

一种方法是使用以下脚本行:

[ "$?" -eq 0 ] && echo "OK" || exit $(echo "NOK" >&2 ; echo 1)

其目的是报告错误并返回错误代码,同时如果选择“OK”路径则保持沉默。

答案3

问题是您正在子 shell 中执行另一个分支(这就是括号中的内容 - 例如在bash(1)手册页中查找compound commands) - 因此exit退出子 shell 而不是执行脚本的 shell。要以更图形化的方式查看它,请sleep在代码的两个版本中放置足够长的时间,然后运行ps faux(对于coreutils的版本ps)或类似的操作pstree来查看进程祖先关系。

现在,如何“修复”它:

  1. 没有什么问题if ... then / else / fi。特别是对于较长的块,它使代码更具可读性。

  2. 如果你想要一个衬垫,那么你可以这样做

    [ "$?" -eq 0 ] && echo "OK" || echo "NOK" >&2 && exit 1
    

    这依赖于正常退出,或者使用组命令

    [ "$?" -eq 0 ] && echo "OK" || { echo "NOK" >&2 ; exit 1; }
    

    检查您的 shell 中的一般可用性以及任何特殊性 - 例如,它应该以换行符或分号终止。

  3. 最全面 - 使用信号/事件处理程序(bash例如,其他 shell 的语法可能有所不同):

    #!/bin/bash
    
    exit_handler () {
        echo "error happened, exiting"
        ... fix things, that may be half baked ...
    }
    
    trap exit_handler EXIT
    
    ... do stuff ...
    

    这使您有机会:

    • use set -e( set -o errexit) 这通常被认为是危险的 -EXIT处理程序可以执行一些操作,例如删除您不想留下的任何临时文件
    • 仅将清理代码放在一处
    • kill也处理其他信号(由例如发送的信号)

相关内容