x="a=b"
`echo $x`
echo $a
我希望第二行生成“a = b”,并在主shell的上下文中执行它,从而生成一个值为a
的新变量b
。
但是,我真正得到的(如果我手动输入命令)是第二行bash: a=b: command not found
为什么会这样?
答案 0 :(得分:4)
尝试
eval $x
(我们需要30个字符才能发布此答案)
答案 1 :(得分:3)
你的第一个回声线在子shell中运行并将其值返回给被调用者。使用$()
可以获得相同的结果,顺便说一句,比反引号更容易使用。
所以,你正在做的是首先运行echo $x
(返回a=b
)。并且,由于反引号,a=b
被返回到shell,它试图将该行作为命令运行 - 显然 - 不起作用。
在shell中尝试:
$(echo ls)
你会清楚地看到发生了什么。
答案 2 :(得分:1)
这是因为bash解析命令行的顺序。它在执行变量和命令替换(例如反引号中的命令)之前查找变量定义(例如a=b
)。因此,当echo $x
被a=b
替换时,bash将此视为变量定义并将其解析为命令为时已晚。如果您只使用$x
作为命令(而不是反引号中的echo),则会发生同样的事情。与@ mvds的答案一样,eval
命令可用于强制命令从头开始重新分配,这意味着它将被识别为变量定义:
$ x="a=b"
$ `echo $x`
-bash: a=b: command not found
$ $(echo $x) # Exact same thing, but with cleaner syntax
-bash: a=b: command not found
$ $x # This also does the same thing, but without some extra steps
-bash: a=b: command not found
$ eval "$x" # This will actually work
$ echo $a
b
$ a= # Start over
$ eval "$(echo "$x")" # Another way of doing the same thing, with extra steps
$ echo $a
b
请注意,在使用eval
时,我将所有对$x
的引用都放在双引号中 - 这是为了防止bash解析的后续阶段(例如分词)发生< em>两次,因为bash将完成其常规解析过程,然后识别eval
命令,然后再次重做整个解析过程 。使用eval
获得意外结果非常容易,这至少可以消除一些潜在的麻烦。
答案 3 :(得分:0)
你在那个有趣的撇号中试过$x
吗?没有echo
,echo似乎只用于显示字符串,而不是执行命令。