在阅读了bash手册之后,关于这post页.

我仍然无法理解eval命令的具体功能,以及它的典型用途.例如,如果我们这样做:

bash$ set -- one two three  # sets $1 $2 $3
bash$ echo $1
one
bash$ n=1
bash$ echo ${$n}       ## First attempt to echo $1 using brackets fails
bash: ${$n}: bad substitution
bash$ echo $($n)       ## Second attempt to echo $1 using parentheses fails
bash: 1: command not found
bash$ eval echo \${$n} ## Third attempt to echo $1 using 'eval' succeeds
one

这里到底发生了什么?美元符号和反斜杠是如何联系在一起的?

推荐答案

eval将一个字符串作为其参数,并像在命令行中键入该字符串一样对其进行计算.(如果你传递了几个参数,它们之间首先会加上空格.)

${$n}是bash中的语法错误.在大括号内,只能有一个变量名,带有一些可能的前缀和后缀,但不能有任意的bash语法,尤其不能使用变量扩展.有一种说法是"名称在此变量中的变量的值",不过:

echo ${!n}
one

$(…)运行子shell中括号内指定的命令(即在继承所有设置(如当前shell的变量值)的单独进程中),并收集其输出.所以echo $($n)以shell命令的形式运行$n,并显示其输出.由于$n的计算结果为1$($n)try 运行命令1,但命令1不存在.

eval echo \${$n}运行传递给eval的参数.展开后,参数为echo${1}.所以eval echo \${$n}运行命令echo ${1}.

请注意,大多数情况下,必须在变量替换和命令替换之间使用双引号(即任何时候有$):"$foo", "$(foo)".Always put double quotes around variable and command substitutions,除非你知道你需要把它们关掉.如果没有双引号,shell将执行字段拆分(即,它将变量的值或命令的输出拆分为单独的字),然后将每个字视为通配符模式.例如:

$ ls
file1 file2 otherfile
$ set -- 'f* *'
$ echo "$1"
f* *
$ echo $1
file1 file2 file1 file2 otherfile
$ n=1
$ eval echo \${$n}
file1 file2 file1 file2 otherfile
$eval echo \"\${$n}\"
f* *
$ echo "${!n}"
f* *

eval不经常使用.在一些shell中,最常见的用途是获取一个直到运行时才知道其名称的变量的值.在bash中,由于${!VAR}语法,这是不必要的.当需要构造包含运算符、保留字等的较长命令时,eval仍然很有用.

Linux相关问答推荐

空字符串和空文件的区别

为什么硬编码的阿拉伯字母与Unicode代码点不具有相同的值

如何从大页分配标准数组内存

cu可以从串口读取,但我自己的C程序不能

仅在 Linux 上出现 AWS RDS `flush tables` 错误的 mysqldump

如何拆分多个分隔符但将它们保留在方括号之间?

使用 sed 从文本文件中删除特定字符串

从 bash shell 等效项在fish shell 上设置 $ANDROID_SDK_ROOT

编译过度对齐的动态分配变量时出现 icpc 错误

如何将通配符参数传递给 bash 文件

将 awk 输出保存到变量

kdevtmpfsi 使用整个 CPU

如何从 linux 的命令行将 Sublime Text 2 文件打开到选项卡,而不是新窗口

根据日期范围过滤日志(log)文件条目

从文本文件中删除奇数行或偶数行

使用sudo apt-get install build-essentials

在 Python 中删除 Root 权限

解压tar tar.bz2 文件报错

crt1.o:在函数_start中:-Linux 中未定义对main的引用

适用于 Windows、Linux、MacOS X 的跨平台脚​​本