Shell 条件后的多个命令列表,&&、||。 Shell 脚本、破折号

Shell 条件后的多个命令列表,&&、||。 Shell 脚本、破折号

我试图在条件之后执行多个命令,例如......

[ $VAR ] || echo "Error msg" ; echo "exit"

和逆

[ -z $VAR ] &&  echo "Error msg" ; echo "exit"

我知道这不会按预期工作,我实际上以前知道怎么做,但忘记了如何做到这一点。我完全了解许多替代方案,例如使用if's 或通过()and括起来{}。使用()将创建一个不会退出正在运行的脚本的子进程。使用{}会起作用,但我知道存在更具可读性的替代方案。

我已经用 完成了这个:,非常完美!我现在完全不记得了,而且我丢失了之前写的剧本。

如果有人知道如何用 来写这个:,我将非常感谢任何帮助!

答案1

更具可读性的替代方案是

if [ -z "$VAR" ]; then
  echo "Error msg" 1>&2
  exit 1
fi

我知道那不是你要找的。但这是你应该写的。在这里使用&&and||有点神秘。我不知道你在记住什么(或者记错了),但无论它是什么,如果这里没有人能猜出它是什么,那么它肯定不符合“可读”的条件。

顺便说一下,请注意 周围的引号$VAR始终在变量替换两边加上双引号,除非您知道为什么需要省略引号以及为什么这样做是安全的。 (你不需要在里面加引号[[ … ]],但你一定要在里面加引号[ … ])。

eval是一种对命令进行分组的偷偷摸摸的方法,但使用它并不具有可读性。

在另一个命令中生成输出的另一种方法是在命令替换中执行此操作。同样,这不符合可读性。

[ "$VAR" ] || exit 1$(echo "error message" >&2)

如果没有某种形式的分组构造(无论是大括号还是其他某种复合形式,例如if/ then/fiwhile/ do/ done),您就无法在主 shell 进程中执行多个命令;除一个外,所有其他都将位于子 shell 中。

答案2

我倾向于使用这样的东西,我认为它可读性很好:

[ -z "$VAR" ] && {
  echo "Line $LINENO: Error msg"
  exit 1
} >&2

对于:,我唯一能想象的是您以某种方式定义了一个函数,但我不知道如何将其转换为允许执行多个命令的块。

man bash:

: [arguments]
        No effect; the command does nothing beyond expanding arguments and
        performing any specified redirections. A zero exit code is returned.

所以我认为唯一的可能性是你是否重新定义:为其他东西。我有兴趣看看这可能是什么。

在任何情况下,将这些参数扩展不加引号是没有意义的,特别是对于[ -zif[ -z $VAR ]为空(或仅包含空格、制表符和换行符,默认值为)而不是[ -z ]$VAR$IFS[ -z 空字符串 ],因此返回 true,因为它是 的缩写[ -n "-z" ]

另外,使用$LINENO退出代码也是一个坏主意,因为仅支持数字 0 到 255(不同 shell 的行为因值超出该范围而异),并且有些具有特殊含义。

答案3

几个选项,没有一个是真正合适的

  1. ${VAR:?"Error msg"}
  2. eval "${VAR:-echo Error msg; exit}"
  3. 算术求值支持三元表达式,但仅适用于值。我不知道这对您的用例有何用处。unset -v a; (( VAR != 0 ? (a=20) : (a=3) )) ; echo $a

答案4

我忍不住认为你实际上是在寻找你说过的东西,不是吗:

[[ -z "$temp" ]] && { echo nope; continue; }

相关内容