带有 || 的条件执行块和括号问题

带有 || 的条件执行块和括号问题

所以这应该很简单。我正在尝试测试脚本顶部的条件,并在条件失败时退出整个脚本,并且我想在退出时执行两条语句。有了单独的exit、没有第二条语句,就可以了,但是无论我如何添加第二条语句,我都无法让它完全退出。隐含的修饰规则是这必须全部在一行上。当对脚本的这一行更改没有按预期工作时,我发现了这一点。剧本继续进行。

首先让我展示一下什么工作。如果 $USER 变量不是“x”,则以下行将完全退出,这很好。我知道这是有效的,因为在终端窗口中输入这一行将关闭该终端窗口(除非您的用户 ID 确实是“x”),所以它实际上是在执行顶级退出:

[ $USER = 'x' ] || exit 1

所以这很好,正如我想要的,只是我想在退出之前回显一条消息;但是,如果我尝试添加回显,则退出不再发生,或者更确切地说,它似乎以“不同的方式”发生,就像在 bash 函数上下文或其他东西中一样。下一行将不是关闭你的终端,这很糟糕。

[ $USER = 'x' ] || (echo "Time to bail" ; exit 1)

我以为分号可能被回声吃掉了,但不,出口似乎被击中了。我怎么知道?我更改了上面的代码,然后回显 $?我看到了我在上面看到的“1”处输入的任何值。当然,我在想要关闭的终端窗口中查看这些值,但它没有关闭。

下一个变体还显示了执行 echo 和第二条语句的第二种方法,但在使用退出时会再次发生完全相同的行为:

[ $USER = 'x' ] || (echo "Time to bail" && exit 1)

我希望这里有人能让这一切不仅不奇怪,而且看起来合理。

那么这是不可能在一行中完成的吗?

( bash --version:)GNU bash, version 4.3.30(1)-release

答案1

你正在搜索的是这样的:

[ "$USER" = "x" ] || { echo "Time to bail"; exit 1; }

{ list; }语句在当前 shell 上下文中执行给定列表中的命令。与符号不同,没有创建子 shell ( list )。括号之间的调用exit将退出该子 shell,而不是父 shell 本身。


您问题中的一行或多行 if 语句的示例在语法上是正确的。我无法重现这种行为。有多少行并不重要; if 语句从不在其主体中启动子 shell。


顺便说一句:我在条件中向变量添加了双引号,因为当变量$USER为空时,构造将扩展为[ = "x" ]无效。使用双引号它会扩展为[ "" = "x" ].

答案2

感谢 @mikeserv 的提示,答案非常简单,并且与认识到括号表示一种非常特殊的分组的重要性有关。括号创建了一个子 shell,这正是我看到缺少所谓的“顶级”出口的原因。

完整的解释是这里,这是关键摘录:

将命令列表放在括号之间会导致创建子 shell 环境...将命令列表放在大括号之间会导致在当前 shell 上下文中执行该列表。

但这里有点不愉快的是,两者不能完全互换,花括号在最后一个花括号之前需要一个分号,而括号则不需要。我正在采用的语法尝试消除分号并使用“&&”形式:

[ $USER == 'x' ] || { echo "保释时间" && exit 1 ; }

总而言之,括号比花括号更好看,而且花括号需要分号,使得单行看起来不像单行。

相关内容