bash 命令替换作为单个命令执行,未解析为 shell 语句

bash command substitution executed as a single command not parsed as shell statement

好像command subsituation是把第一个token作为command,剩下的作为command的参数, 未解析为 shell 语句。但是 bash 手册说:

Bash performs the expansion by executing command in a subshell environment

例子

$ c="echo 123 ; echo 124"
$ d=`$c`
$ echo $d
123 ; echo 124

为什么 d 是 13 ; echo 124 而不是 123 124

发生这种情况是因为在 d=`$c` 中,命令不是 echo 123 ; echo 124,而是 $c

这意味着 Bash 遵循所谓的简单命令的评估步骤,described in detail in POSIX

跳过无关部分,涉及的步骤是:

  1. The words that are not variable assignments or redirections shall be expanded. If any fields remain following their expansion, the first field shall be considered the command name and remaining fields are the arguments for the command.

所以$c按照规则展开:

Tilde expansion (see Tilde Expansion), parameter expansion (see Parameter Expansion), command substitution (see Command Substitution), and arithmetic expansion (see Arithmetic Expansion) shall be performed, beginning to end. See item 5 in Token Recognition.

$c 变成 echo 123 ; echo 124

Field splitting (see Field Splitting) shall be performed on the portions of the fields generated by step 1, unless IFS is null.

echo 123 ; echo 124变为echo123;echo124

If there is a command name, execution shall continue as described in Command Search and Execution .

echo 使用参数 123;echo124 调用并打印出来。

为了让它按照你预期的方式工作,必须有一个步骤“展开后,根据 shell 语法规则获取结果字符串并再次解析它”,但没有.

也是好事,因为想象一下如果 read -p "Name: " name; 会让你输入 "; rm -rf /; " 并将 echo "Hello $name" 变成 echo "Hello "; rm -rf /; ""