使用 `eval $cmd` 和仅使用 `$cmd` 在 bash 中有什么区别吗?

Is there any difference in bash between using `eval $cmd` and just `$cmd`?

在 bash 中,您可以通过两种不同的方式将字符串视为命令(和 运行 它):

#!/bin/bash
cmd="echo -n sometext"
eval $cmd    # Not sure if quotes make a difference here

#!/bin/bash
cmd="echo -n sometext"
$cmd    # Not sure if quotes make a difference here either

两者有什么区别吗? cmd 周围的引号是否会有所不同?性能怎么样?

是的,有区别:) 您需要先了解 eval 的工作原理。基本上,eval 是一个 shell 内置命令。传递给 eval 的任何参数都首先被视为字符串。 让我们举个例子:

 cmd="echo -n sometext"
 eval $cmd 

该命令完整的运行过程如下:

 eval $cmd
 + eval echo -n sometext
 ++ echo -n sometext
 sometext

在这里,首先对 $cmd 进行求值,然后将整个字符串作为参数传递给 eval 命令。然后 eval 评估命令,将第一个参数视为 "command or an executable file",然后将 运行 视为普通命令。因此,这里为执行完整命令执行了 2 轮评估。 (注意:上面的 + 符号显示在 bash -x 模式下使用时的逐步执行)

主要后果在于变量膨胀。 eval 我们有两轮扩张。一种当然是在定义cmd的时候,一种是在执行eval的时候。

var="inital"
cmd="echo -n $var $var"
var="chanded in the mean time"
eval $cmd
inital chanded in the mean time

然而,当你只使用 $cmd 而没有使用 eval 时,bash 会处理从变量扩展到最终执行的所有事情。仅查看调试 window 详细信息,而仅 运行ning $cmd

$cmd
+ echo -n sometext
sometext

性能方面,直接使用$cmd就足够了。但是,当您尝试使用一些需要环境更改的外部命令或脚本时,您可以使用 eval

cmd="echo -n sometext"中,引号是必须的,否则在"echo"、bash之后会报如下错误:

cmd=echo -n sometext
-n: command not found

希望解释对您有所帮助。