反引号命令封装

viu*_*ser 2 shell bash command-substitution

test@debian:~$ echo `echo \`echo "uh!"\``
uh!
Run Code Online (Sandbox Code Playgroud)

Bash 是如何做到这一点的?似乎它首先执行非转义反引号中的表达式,它返回(双引号“”被删除,对吗?):

`echo uh!`
Run Code Online (Sandbox Code Playgroud)

所以我们有一个输入等价于:

test@debian:~$ echo `echo uh!`
Run Code Online (Sandbox Code Playgroud)

(旁注:真的,为什么它有效?因为:

test@debian:~$ echo `echo uh!`
-bash: !`: event not found
Run Code Online (Sandbox Code Playgroud)

)

然后 Bash 再次执行反引号中的表达式,它给出:

test@debian:~$ echo uh!
Run Code Online (Sandbox Code Playgroud)

这最终给了我们输出:

uh!
Run Code Online (Sandbox Code Playgroud)

那正确吗?并且如何将四个 echo反引号表达式相互封装?

Sté*_*las 6

取决于您的版本bash

bash-4.2$ echo `echo \`echo "uh!"\``
bash: !"\``: event not found
bash-4.3$ echo `echo \`echo "uh!"\``
uh!
Run Code Online (Sandbox Code Playgroud)

bash-4.3,!"不再有资格作为历史事件指示符,因此历史扩展不适用。

除此之外,它只是普通的反引号嵌套语法。在反引号内,反斜杠字符被重载(再次)以再次执行嵌套扩展。

您可以根据需要嵌套多个级别:

echo `echo \`echo \\\`echo \\\\\\\`echo whatever\\\\\\\`\\\`\``
Run Code Online (Sandbox Code Playgroud)

这是繁琐的等价物:

echo $(echo $(echo $(echo $(echo whatever))))
Run Code Online (Sandbox Code Playgroud)

但是请注意,在两个版本中,命令替换都受分词的影响。所以,你想引用它们来防止它。

随着bashdashpdkshyashzsh,它是相对容易:

echo "`echo "\`echo "\\\`echo "\\\\\\\`echo whatever\\\\\\\`"\\\`"\`"`"
Run Code Online (Sandbox Code Playgroud)

使用 Bourne 或 Korn shell,您还需要转义"虽然,因此变为:

echo "`echo \"\`echo \\\"\\\`echo \\\\\\\"\\\\\\\`echo whatever\\\\\\\`\\\\\\\"\\\`\\\"\`\"`"
Run Code Online (Sandbox Code Playgroud)

与之比较:

echo "$(echo "$(echo "$(echo "$(echo whatever)")")")" 
Run Code Online (Sandbox Code Playgroud)