为什么 subshel​​l returns if: command not found

why does subshell returns if: command not found

让我们假设以下脚本:

echo "if test 1 -eq  ; then echo ls;fi" | tee /tmp/toto
cat /tmp/toto
$(cat /tmp/toto)

同时 运行使用此命令对其进行设置: ./non_secure_script 1

我收到以下错误: if: command not found

但是,下面的命令运行成功了:

$(if test 1 -eq 1; then echo ls;fi)

为什么会这样?

因为大多数解析 traditional/standard(即不是 *csh、rc 等)shell 输入,特别是识别像 if 这样的保留字和像 [=11= 这样的复合命令] 扩展如 $( command ) 之前完成。请参阅页面后面的 sequence defined by POSIX,特别是步骤 2 和 3 以及第 2.2-2.4 节,而页面后面的步骤 4 和第 2.5-2.6 节,不是 'wordexp' 作为链接 (!!!).

如果您在 shell 上执行 $(/tmp/toto)$(. /tmp/toto) - 或 $(source /tmp/toto) 作为同义词 - 它会 执行 子 shell 和 return 中的 if 构造到主 shell 只有字符串 ls (或什么都没有)。由于主 shell 已将其解析为简单命令(请参阅上面链接页面上的第 2.9.1 节)before 扩展,并且 ls 是有效的simple-command,执行成功。因为分词和路径名扩展(通常称为 globbing)是作为 2.6 节中扩展的最后步骤完成的(除非禁用),returning 一个包含多个 space 分隔词的字符串,例如 ls -la 会起作用,除非它们包含像 ?* 这样的 glob 运算符,但像 ls -la 'file with spaces' 这样的引用不起作用。

你的第二个案例 $(if...fi) 出于同样的原因工作;它在子 shell 和 return 中执行 if-construct 仅 ls 在主 shell 中执行,这是一个有效的简单命令。