以下代码将导致“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 执行以下操作:
将标记解析为简单的和复合命令(参见 Shell 命令)。
执行各种外壳扩展(请参阅 Shell 扩展),将扩展的标记分解为文件名列表(请参阅文件名扩展)以及命令和参数。
...
执行命令(请参阅执行命令)。
语句中的块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 模式”生效时发生的变化:
- 如果在赋值语句后面没有命令名时发生变量赋值错误,则非交互式 shell 将以错误状态退出。