在bash中,$( )与` `(反引号)都是用来作命令替换的。
命令替换与变量替换差不多,都是用来重组命令行的,先完成引号里的命令行,然后将其结果替换出来,再重组成新的命令行。
举个例子:
[root@centos7 ~]# echo today is $(date "+%Y-%m-%d")
today is 2022-11-23
[root@centos7 ~]# echo today is `date "+%Y-%m-%d"`
today is 2022-11-23
操作上,这两者都是达到相应的效果,但是建议使用$( ),理由如下:
- ``(反引号)很容易与''(单引号)搞混乱,尤其对初学者来说。
- 在多层次的复合替换中,``必须要额外的转义字符处理(反斜线),而$( )比较直观。
- 但是,$( )的弊端是,并不是所有的类unix系统都支持这种方式,但反引号是肯定支持的。
eval命令
eval可以读取一连串的参数,然后按照参数特性来执行。参数数目不限,彼此之间用分号隔开。
eval会对后面的命令进行两遍扫描
如果第一遍扫描后,命令是个普通命令,则执行此命令;如果命令中含有变量的间接引用,则保证间接引用的语义。也就是说,eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。
因此,eval命令适用于那些一次扫描无法实现其功能的变量。
eval 执行以下两个步骤:
第一步,执行变量替换,类似与C语言的宏替代;
第二步,执行替换后的命令串。
下面来看几个例子:
例:执行含有带字符串的命令
[root@centos7 fan]# cat name
zhongguo
[root@centos7 fan]# test="cat name"
[root@centos7 fan]# echo $test
cat name
[root@centos7 fan]# eval $test
zhongguo
看上面的例子,把cat test赋值给变量WORD。当我们执行echo WORD就是将变量WORD的值列出来,并不能得到test中的内容;然而eval WORD则能显示文件中的内容,因为eval命令对后面的命令进行了两次扫描,第一次将WORD替换为 cat test,第二次执行cat test。
这些需要进行两次扫描的变量有时被称为复杂变量。
eval命令不仅可以回显复杂变量,也可以用于回显简单变量。
例:回显简单变量
[root@centos7 fan]# path="/home/bin/"
[root@centos7 fan]# a="\$path/file1"
[root@centos7 fan]# echo $a
$path/file1
[root@centos7 fan]# eval $a
-bash: /home/bin//file1: No such file or directory
[root@centos7 fan]# eval echo $a
/home/bin//file1
例:获取传给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