以下代码将导致“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"
Run Code Online (Sandbox Code Playgroud)
输出是
line 4: ${$1:='val'}: bad substitution
line 7: ${$1:='val'}: bad substitution
This does run
Run Code Online (Sandbox Code Playgroud)
再说一遍 - 我对修复错误替换错误消息不感兴趣,我了解如何做到这一点以及为什么会发生这种情况。我想了解的是,为什么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)
正如 Kusalananda 在评论中指出的那样,这本质上与在复合命令中设置 Bash 选项中描述的相同。
\n来自Bash 参考:
\n\n\n下面简单描述一下shell\xe2\x80\x99s读取并执行命令时的操作。基本上,shell 执行以下操作:
\n\n
\n- \n
将标记解析为简单命令和复合命令(请参阅 Shell 命令)。
\n- \n
执行各种shell 扩展(请参阅 Shell 扩展),将扩展的标记分解为文件名列表(请参阅文件名扩展)以及命令和参数。
\n- \n
...
\n- \n
执行命令(请参阅执行命令)。
\n
语句中的块if是一个复合命令,并且存在扩展错误,即VAR=${$1:=\'val\'},因此整个块失败,永远不会到达步骤 6,并且echo永远不会执行第一个。
请注意,这种对扩展错误的特殊处理违反了 POSIX 标准,该标准在第 2.8.1 节中规定扩展错误应退出非交互式 shell。
\n在 POSIX 模式下,Bash 确实以一致的方式运行:
\n% bash horse \nhorse: line 2: ${$1:=\'val\'}: bad substitution\nhorse: line 4: ${$1:=\'val\'}: bad substitution\nThis does run\n% bash --posix horse \nhorse: line 2: ${$1:=\'val\'}: bad substitution\nRun Code Online (Sandbox Code Playgroud)\n为了宣告 Bash 无罪,记录了这种违规行为:
\n\n\n以下列表是当 \xe2\x80\x98POSIX 模式\xe2\x80\x99 生效时,\xe2\x80\x99s 发生的变化:
\n\n
\n- 如果在赋值语句后面没有命令名时发生变量赋值错误,则非交互式 shell 将以错误状态退出。
\n