``和$()的区别及eval详解

命令替换

在bash中,$( )与` `(反引号)都是用来作命令替换的。
命令替换与变量替换差不多,都是用来重组命令行的,先完成引号里的命令行,然后将其结果替换出来,再重组成新的命令行。

eg:
这里写图片描述

$( )与``

在操作上,这两者都是达到相应的效果,但是建议使用$( ),理由如下:

  1. ``很容易与”搞混乱,尤其对初学者来说。
  2. 在多层次的复合替换中,``必须要额外的转义字符处理(反斜线),而$( )比较直观。
  3. 最后,$( )的弊端是,并不是所有的类unix系统都支持这种方式,但反引号是肯定支持的。

eval命令

eval可以读取一连串的参数,然后按照参数特性来执行。参数数目不限,彼此之间用分号隔开。
eval会对后面的命令进行两遍扫描
如果第一遍扫描后,命令是个普通命令,则执行此命令;如果命令中含有变量的间接引用,则保证间接引用的语义。也就是说,eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。
因此,eval命令适用于那些一次扫描无法实现其功能的变量。

eval 执行以下两个步骤:
第一步,执行变量替换,类似与C语言的宏替代;
第二步,执行替换后的命令串。

下面来看几个例子:
例:执行含有带字符串的命令

[root@localhost ~]# cat test
Hello World!
[root@localhost ~]# WORD="cat test"
[root@localhost ~]# echo $WORD
cat test
[root@localhost ~]# eval $WORD
Hello World!

看上面的例子,把cat test赋值给变量WORD。当我们执行echo WORD就是将变量WORD的值列出来,并不能得到test中的内容;然而eval WORD则能显示文件中的内容,因为eval命令对后面的命令进行了两次扫描,第一次将WORD替换为 cat test,第二次执行cat test。
这些需要进行两次扫描的变量有时被称为复杂变量。
eval命令不仅可以回显复杂变量,也可以用于回显简单变量。
例:回显简单变量

[root@localhost ~]# NAME=filename
[root@localhost ~]# echo $NAME
filename
[root@localhost ~]# eval echo $NAME
filename

例:获取传给shell的最后一个参数
之前我们已经了解过shell语法,知道最后一个参数是$#,看如下代码,用eval可得到其内容。

[root@localhost ~]# cat test.sh
#!/bin/bash
echo "\$$#"

eval echo "\$$#"
[root@localhost ~]# chmod u+x test.sh
[root@localhost ~]# ./test.sh first last
$2
last

例:条件筛选
在file文件中写入两列数据,第一列对应KEY 、第二列为VALUE,使用eval命令将KEY与VALUE的值对应起来,从文件中读取:

[root@localhost ~]# cat file
NAME ZHANG
AGE 20
SEX NV
[root@localhost ~]# cat test.sh
#!/bin/bash

while read KEY VALUE
do
    eval "${KEY}=${VALUE}"
done < file
echo "$NAME $AGE $SEX"
[root@localhost ~]# ./test.sh
ZHANG 20 NV

注意:
1、eval 不能获得函数处理结果。
2、shell中eval 嵌套无意义,在其他语言中可以通过 eval(eval(“code”)) ,来执行动态生成的 code 的返回,而由于shell 中 eval 将后面的 eval 命令简单当作命令字符串执行,失去了嵌套作用,嵌套被命令替换取代。

你可能感兴趣的:(shell)