【发布时间】:2018-03-23 15:28:19
【问题描述】:
假设我们有一个命令输出一个变量赋值字符串,比如'var=foo',如果我把这个命令放在命令替换中,看起来像
$(echo var=foo),会导致“command not found”错误。
[223212 dot@anne ~]$ var=foo
[223226 dot@anne ~]$
[223230 dot@anne ~]$ $(var=foo)
[223235 dot@anne ~]$
[223236 dot@anne ~]$ $(echo var=foo)
bash: var=foo: command not found
[223240 dot@anne ~]$
[224909 dot@anne ~]$ $(echo ls)
a b c d
[225036 dot@anne ~]$
[225110 dot@anne ~]$ $(echo $(var=foo))
[225116 dot@anne ~]$
既然我们可以像这样$(var=foo)(虽然我认为这毫无意义),我们可以直接在命令替换中进行变量赋值,并且$(echo ls)也可以正常工作, 为什么在命令替换中输出赋值导致错误?
这是man bash关于命令替换:
命令替换允许命令的输出替换 命令名称。
Bash 通过在 a 中执行命令来执行扩展 subshell 环境并将命令替换替换为 命令的标准输出,所有尾随换行符都被删除。
据我了解,$(echo var=foo) 应该替换为 var=foo,就像 $(var=foo) 一样。
我理解错了吗?
【问题讨论】:
-
当您使用命令替换时,您应该将输出分配给某些东西,即
foo=$(echo buzz)。当然“echo”在这里没有意义,它通常不需要命令替换,你通常只需使用foo=buzz -
这很有趣,看起来 Bash 将子进程的输出视为命令名称,而不是其他指令。就像您输入了
var\=foo,因此找不到命令错误。尝试评估结果以解决此问题:eval $(echo var=foo). -
我知道这没有意义,而且我知道我可以使用 eval 来解决这样的问题。但这不是重点。使用 echo 只是一个简单的例子,实际上我使用的是 $(gpg -qd file)。
-
如果您使用的是
$(pgp -qd file),那么您可能会遇到BashFAQ #50 中详细描述的问题(因为从不带引号的命令替换生成的命令具有完全相同的警告)通过不带引号的字符串扩展生成)。 -
@Pawamoy,这不足为奇——唯一没有引用的扩展结果经过的解析阶段是字符串拆分和通配;在该点之前识别分配。
eval可能是 OP 想要的,但它是 dangerous,最好不要在没有明确警告的情况下推荐。
标签: bash