2.1.2 嵌套变量
学习目标
这一节,我们从 基础知识、简单实践、小结 三个方面来学习
基础知识
场景现象
场景1:我们知道,命令变量的的表现样式:
ver=$(命令)
-- 执行原理是,当`` 或者 $() 范围中存在能够正常解析的命令的话,会先执行命令,然后将命令执行的结果交个一个变量名。
场景2:它还有另外一种样式 -- 普通变量的第三种样式双引号
ming=shuji; name="wang-$ming"
-- 解析原理:双引号会首先查看变量值范围内是否有可以解析的变量名,如果有的话,将解析后的结果放到变量值范围内,组合成一个新的变量值,然后交给变量名。
上面的两种场景的特点就在于,一个命令行中,借助于$() 或者 "" 发起一次隐藏的命令执行,但是有些场景下,表面上的一个命令需要发起更深一层的命令执行才可以实现指定的功能。在这种场景下,无论是$() 还是 ""都无法满足要求了
场景示例
循环遍历演示
[root@localhost ~]# for i in {1..10}; do echo "$i "; done
1
2
3
4
5
6
7
8
9
10
示例解读:这里出现一层隐藏命令执行
1 {1..10} 会自动进行命令解析
[root@localhost ~]# echo {1..10}
1 2 3 4 5 6 7 8 9 10
然后执行for命令
for i in 1 2 3 4 5 6 7 8 9 10
双层隐藏命令解读
[root@localhost ~]# n=10
[root@localhost ~]# for i in {1..$n}; do echo "$i "; done
{1..10}
示例解读:
在for语句中,其实我们的目的与上面的演示一样,但是区别在于这里有两层隐藏的命令执行
1 $n 需要解析成 10
2 {1..10} 需要解析成 1 2 3 4 5 6 7 8 9 10
最后执行 for命令 for 1 2 3 4 5 6 7 8 9 10
问题:
linux命令行,默认情况下是无法执行两层隐藏命令的执行的,在有些场景中,我们可以通过$() 来实现多层命令的解读,示例如下:
[root@localhost ~]# cmd=who
[root@localhost ~]# echo $(${cmd}ami)
root
但是,这里我们无法实现,因为 {1..10} 不是命令。
[root@localhost ~]# for i in $({1..$n}); do echo "$i "; done
-bash: {1..10}: 未找到命令
解决方法
在shell中,它提供了一个专属的命令,可以实现多层隐藏命令的解析,不仅仅能够解析,还能够将相关环境的属性重现,从而实现多层隐藏命令的顺利执行。这个命令就是 eval。
eval原理
1 eval命令将会首先扫描命令行整体
2 发现解析则解析,发现执行则预先执行,实现所有隐藏命令的成功执行
3 将隐藏命令执行的最终结果进行置换
4 最后执行命令行表面的命令。
简单实践
实践1-eval简单实践
for循环演示
[root@localhost ~]# n=10
[root@localhost ~]# for i in $(eval echo {1..$n}); do echo "$i "; done
1
2
3
4
5
6
7
8
9
10
示例解读
1 命令改造$(eval echo {1..$n})
1-1 $n先解析为10,命令替换为 {1..10}
1-2 通过 eval 带入 echo 命令环境
1-3 $() 执行 echo {1..10} 输出为 1 2 3 4 5 6 7 8 9 10
2 整体置换命令结果
for i in 1 2 3 4 5 6 7 8 9 10
实践2-eval的命令扩展演示
查看文件内容
[root@localhost ~]# echo 'hello-in-world' > infile.txt
[root@localhost ~]# cat infile.txt
hello-in-world
脚本内容演示
[root@localhost ~]# echo 'hello-in-world' > infile.txt
[root@localhost ~]# cat infile.txt
hello-in-world
[root@localhost ~]# cmd="cat infile.txt"
[root@localhost ~]# echo $(${cmd})
hello-in-world
[root@localhost ~]# echo ${cmd}
cat infile.txt
不是我们想要的,我们可以借助于eval 和 $() 方式来实现隐藏命令的解读
[root@localhost ~]# eval ${cmd}
hello-in-world
[root@localhost ~]# echo $(${cmd})
hello-in-world
实践3-eval变量名的预制解析
定制嵌套的环境变量
[root@localhost ~]# str=a
[root@localhost ~]# num=1
[root@localhost ~]# $str$num=hello
-bash: a1=hello: 未找到命令
借助于eval命令来实现
[root@localhost ~]# eval $str$num=hello
[root@localhost ~]# echo $a1
hello
借助于eval实现变量名的嵌套
[root@localhost ~]# eval $str=$a1
[root@localhost ~]# echo $a
hello
解读:
$str 就是 a,$a1就是hello,
eval执行的命令就是 a=hello