Linux:执行命令的命令eval与Bash解析命令的方式

相关阅读

Linuxhttps://blog.csdn.net/weixin_45791458/category_12234591.html?spm=1001.2014.3001.5482


eval命令用于接收参数,并将这些参数作为一行命令执行,这也许会使人困惑,为什么我不能直接执行命令而需要使用eval命令间接执行呢?本文将解开这些疑惑。

eval命令的语法如下所示,可以看到它非常简单。

bash 复制代码
用法
eval [args]
参数
args 用于组成一行命令的参数

下面简单了解一下Bash解析一行命令的过程,这有利于之后学习eval命令。

1、Bash首先根据在考虑双引号、单引号、转义符的前提下,根据空格、制表符、换行符、命令结束符(;)、管道命令符(|)、重定向命令符(>,<)、左右括号、后台运行符(&)等将一行命令拆成多个命令和每个命令相应的token。

2、随后Bash对每个命令的第一个token进行别名替换检查,如该token是一个别名,则会进行替换。

3、之后Bash会对第一条命令(注意不是全部命令),依次进行大括号替换(Brace Expansion)、波浪号替换(Tilde Expansion)、变量替换(Parameter Expansion)、命令替换(Command Expansion)、算数替换(Arithmetic Expansion)、Token重解析(Word Splitting)和路径名替换(Pathname Expansion)。

4、最后才是执行命令,即将第一个token当做命令名,其他token作为参数和选项。

所以,下面这种执行命令的方式是可行的,即使其有点奇怪。

bash 复制代码
[***@EDA ~]$ command='echo Hello' #这里需要使用双引号或单引号,这样等号后面的字符串才会被解析为一个token
[***@EDA ~]$ $command #其经历了变量替换、Token重解析后变成了两个token:echo和hello,所以命令名为echo,参数为Hello
Hello
[***@EDA ~]$ 'echo Hello' #直接使用字符串是不行的,因为其会被解析为一个token,直到最后被当做一个命令名
bash: echo Hello: command not found... #报错,无法找到命令

但是直接使用变量替换去执行命令也是有问题的,它可行完全是因为Token重解析,如果此时变量的字符串代表两条命令,则会出现问题,如下所示。

bash 复制代码
[***@EDA ~]$ command='echo Hello;echo World'  #本意是想输出Hello World
[***@EDA ~]$ $command
Hello;echo World   
#由于进行变量替换时已经是第3步了,无法再将一行命令解析为多个命令(第1步),
#此时的Token重解析将Hello;echo World整体作为了echo的参数

但是如果使用eval命令就可以解决上面两个问题,因为它可以将其参数重新组织为一行命令,并重新经历上面所说的4步过程。

bash 复制代码
[***@EDA ~]$ eval 'echo Hello' 
#即使echo Hello作为一个token是eval命令的参数,
#但eval将这个字符串作为一行命令,所以其又会被解析成echo和Hello两个token并正确执行
Hello
bash 复制代码
[***@EDA ~]$ command='echo Hello;echo World'  #本意是想输出Hello World
[***@EDA ~]$ eval $command 
#首先进行变量替换,结果为eval echo Hello;echo World,Token重解析后它们成为eval命令的三个参数,
#即echo、Hello;echo和World,最后被组织成一行命令,并解析为两条命令,即echo Hello和echo World
Hello
World         

一个变量替换的结果不会再进行变量替换,如下所示,但使用eval命令可以做到。

bash 复制代码
[***@EDA ~]$ a=1
[***@EDA ~]$ b='$a'  #这里使用单引号阻止变量替换
[***@EDA ~]$ echo $b
$a                   #结果不会进一步替换
[***@EDA ~]$ eval echo $b #首先$b进行变量替换变成$a,随后echo和$a作为eval的两个参数,被组织成一行命令,echo $a,并再次变量替换为echo 1,最后输出1
1

最后建议谨慎使用eval命令,因为它能将传给他的参数作为命令执行,即使你可能不知道这个参数的具体值,这会导致安全性问题。

相关推荐
萧曵 丶3 分钟前
Linux 业务场景常用命令详解
linux·运维·服务器
豆是浪个38 分钟前
Linux(Centos 7.6)命令详解:ps
linux·windows·centos
乾元43 分钟前
ISP 级别的异常洪泛检测与防护——大流量事件的 AI 自动识别与响应工程
运维·网络·人工智能·安全·web安全·架构
Run_Teenage1 小时前
Linux:深刻理解缓冲区
linux
youxiao_902 小时前
kubernetes 概念与安装(一)
linux·运维·服务器
凡梦千华2 小时前
logrotate日志切割
linux·运维·服务器
wdfk_prog2 小时前
[Linux]学习笔记系列 -- [fs][proc]
linux·笔记·学习
ELI_He9992 小时前
Airflow docker 部署
运维·docker·容器
拜托啦!狮子3 小时前
安装和使用Homer(linux)
linux·运维·服务器
liulilittle3 小时前
XDP VNP虚拟以太网关(章节:一)
linux·服务器·开发语言·网络·c++·通信·xdp