Bash 为什么需要为$添加转义字符?在评估中?

Bash 为什么需要为$添加转义字符?在评估中?,bash,eval,Bash,Eval,下一步: $ export A=1 $ eval "echo $A; echo $A; lll; echo $?" 输出为: 1 1 -bash: lll: command not found 0 我不知道为什么我无法获取lll的退出代码,我碰巧尝试了下一步: $ export A=1 $ eval "echo $A; echo $A; lll; echo \$?" 1 1 -bash: lll: command not found 127 您可以看到上面的工作,同时下一步也可以工作: $

下一步:

$ export A=1
$ eval "echo $A; echo $A; lll; echo $?"
输出为:

1
1
-bash: lll: command not found
0
我不知道为什么我无法获取
lll
的退出代码,我碰巧尝试了下一步:

$ export A=1
$ eval "echo $A; echo $A; lll; echo \$?"
1
1
-bash: lll: command not found
127
您可以看到上面的工作,同时下一步也可以工作:

$ export A=1
$ eval "echo \$A; echo \$A; lll; echo \$?"
1
1
-bash: lll: command not found
127

我想知道,为什么我必须在
$?
之前添加一个
\
?另外,为什么在
\
之前
$A
不是必须的?

请记住,因为您已经接受了要计算的整个表达式,所以用双引号括起来。这意味着在调用
eval
之前,将展开其中的所有参数。如果不转义
$?
,则要展开的参数是
A
。在运行
eval
之前,您会得到
A
的值(这是您想要的),但在运行
eval
之前,您也会得到
的值(这不是您想要的)。反斜杠会将文本
$
传递给
eval
,从而推迟计算状态代码的时间

$ eval "echo $A; echo $A; lll; echo $?"
用双引号括起来的变量将展开。上一行与以下内容相同:

$ eval "echo 1; echo 1; lll; echo 0"
事实上,这个字符串正是
eval
作为参数接收的字符串。您甚至不需要为此导出一个

为了达到您想要的效果,应该将字符串括在单引号中。这样,变量就不会再展开,
eval
接收与键入字符串完全相同的字符串作为参数


尝试这两组命令

$ export A=1
$ B="echo $A; echo $A; lll; echo $?"
$ eval $B
$ A=2
$ eval $B
vs

那是不同的,不是吗

$ export A=1
$ B='echo $A; echo $A; lll; echo $?'
$ eval $B
$ A=2
$ eval $B