Bash 'if' 语句在命令失败时提前退出

Bash 'if' 语句在命令失败时提前退出

以下代码将导致“if”语句提前退出,并且不执行“if”块中的“echo”命令。我想知道为什么这种情况仅发生在“if”块中,但不会发生在脚本的主要部分中。注意:我知道将 ':=' 更改为 ':-' 将解决问题 - 我不想解决问题,我希望了解导致问题发生的 'if' 块的执行环境之间的差异首先。

#!/bin/bash

if true; then
        VAR=${$1:='val'}
        echo "This does not run"
fi


VAR=${$1:='val'}
echo "This does run"

输出是

line 4: ${$1:='val'}: bad substitution
line 7: ${$1:='val'}: bad substitution
This does run

再说一遍 - 我对修复错误替换错误消息不感兴趣,我了解如何做到这一点以及为什么会发生这种情况。我想了解的是,为什么echo "This does not run"当“if”块中的上面有一个错误的替换时,该行不会运行。

转载于以下 bash 版本:

GNU bash,版本 5.1.16(1)-release (x86_64-pc-linux-gnu)

GNU bash,版本 4.2.46(2)-release (x86_64-redhat-linux-gnu)

答案1

正如 Kusalananda 在评论中指出的那样,这本质上与中描述的相同在复合命令中设置 Bash 选项

bash 参考

下面简单描述一下shell读取并执行命令时的操作。基本上,shell 执行以下操作:

  1. 将标记解析为简单的和复合命令(参见 Shell 命令)。

  2. 执行各种外壳扩展(请参阅 Shell 扩展),将扩展的标记分解为文件名列表(请参阅文件名扩展)以及命令和参数。

  3. ...

  4. 执行命令(请参阅执行命令)。

语句中的块if复合命令并且有一个扩展错误,即VAR=${$1:='val'},因此整个块失败,永远不会到达第 6 步,并且echo永远不会执行第一个。

请注意,这种对扩展错误的特殊处理违反了 POSIX 标准,即第2.8.1节扩展错误应退出非交互式 shell

在 POSIX 模式下,Bash 确实以一致的方式运行:

% bash horse 
horse: line 2: ${$1:='val'}: bad substitution
horse: line 4: ${$1:='val'}: bad substitution
This does run
% bash --posix horse 
horse: line 2: ${$1:='val'}: bad substitution

为了宣告 Bash 无罪,这种违规行为是有记录的

以下列表是“POSIX 模式”生效时发生的变化:

  1. 如果在赋值语句后面没有命令名时发生变量赋值错误,则非交互式 shell 将以错误状态退出。

相关内容