命令代换
在shell编程中,一共有两种命令代换方式:反引号和$() 。shell先执行该命令,然后将输出结果立刻代换到当前命令行中。
比如:我们用反引号替换date命令,$()代换pwd:
[root@localhost ~]# DATE=`date`
[root@localhost ~]# echo $DATE
2017年 06月 26日 星期一 08:01:59 CST
[root@localhost ~]# DATE=$(pwd)
[root@localhost ~]# echo $DATE
/root
1
2
3
4
5
6
[root@localhost~]# DATE=`date`
[root@localhost~]# echo $DATE
2017年06月26日星期一08:01:59CST
[root@localhost~]# DATE=$(pwd)
[root@localhost~]# echo $DATE
/root
当然,和$() 仅仅是命令代换,相当于多产生了一个别名,而并没有将原先命令替换。
既然是两种命令代换,那么是否有什么区别或适用场景吗?
在多层次的符合代换命令中,反引号需要添加"\"转义,而$()则不需要,比如下列示例:
[root@localhost ~]# echo `cat \`ls file\``
hello world!
[root@localhost ~]# echo $(cat $(ls file))
hello world!
1
2
3
4
[root@localhost~]# echo `cat \`ls file\``
helloworld!
[root@localhost~]# echo $(cat $(ls file))
helloworld!
eval命令
eval首先会扫描命令行进行所有的置换 ,然后在执行该命令,因此,eval适用于那些一次扫描无法实现其功能的变量。
所以,eval命令会通过以下两个步骤来执行某个行为:
① 执行命令替换,与宏替换较为相似
② 执行替换后的命令
1
2
3
①执行命令替换,与宏替换较为相似
②执行替换后的命令
下面我们touch一个file文件,内容为"Hello World",定义一个内容是cat file的字符串变量,用echo引用该变量,则直接打印的是该字符串,而用eval则可以显示file的内容。
[root@localhost mytest]#
[root@localhost mytest]# cat file
Hello World!
[root@localhost mytest]# data="cat file"
[root@localhost mytest]# echo $data
cat file
[root@localhost mytest]# eval $data
Hello World!
1
2
3
4
5
6
7
8
[root@localhostmytest]#
[root@localhostmytest]# cat file
HelloWorld!
[root@localhostmytest]# data="cat file"
[root@localhostmytest]# echo $data
catfile
[root@localhostmytest]# eval $data
HelloWorld!
原因在于eval命令第一次扫描进行了变量置换,第二次扫描执行了该字符串所包含的命令cat file。
除此之外,eval另一个功能是获取shell脚本的最后一个参数,我们用以下shell测试:
#!/bin/bash
echo "\$$#"
eval echo "\$$#"
1
2
3
4
#!/bin/bash
echo"\$$#"
evalecho"\$$#"
[root@localhost myshell]# ./eval.sh 10 20 30
$3 //参数个数
30 //最后一个参数
1
2
3
[root@localhostmyshell]# ./eval.sh 10 20 30
$3//参数个数
30//最后一个参数
注意:
① eval不能获得函数处理结果
② eval不能嵌套,或者说嵌套没有任何意义。比如:eval(eval("happy")),eval将后面的eval命令当做命令字符串去执行,失去了嵌套作用,嵌套被指令替换取代。