shell中的eval学习与应用

2023-11-07

http://blog.csdn.net/hshl1214/article/details/7534589

一、bash命令处理的12个步骤

1、将命令行分成由固定元字符集分隔的记号; 

SPACE, TAB, NEWLINE, ; , (, ),<, >, |,&
记号类型包括单词,关键字,I/O重定向符和分号。

2、检测每个命令的第一个记号,查看是否为不带引号或反斜线的关键字。

如果是一个开放的关键字,如if和其他控制结构起始字符串,function,{或(,则命令实际上为一复合命令。shell在内部对复合命令进行处理,读取下一个命令,并重复这一过程。如果关键字不是复合命令起始字符串(如then等一个控制结构中间出现的关键字),则给出语法错误信号。

3、依据别名列表检查每个命令的第一个关键字;

如果找到相应匹配,则替换其别名定义,并退回第一步;否则进入第4步。该策略允许递归别名,还允许定义关键字别名。如aliasprocedure=function

4、执行大括号扩展,例如a{b,c}变成ab ac

5、如果~位于单词开头,用$HOME替换~。

使用usr的主目录替换~user。

6、对任何以符号$开头的表达式执行参数(变量)替换;

7、对形式$(string)的表达式进行命令替换;

这里是嵌套的命令行处理。

8、计算形式为$((string))的算术表达式;

9、把行的参数,命令和算术替换部分再次分成单词,这次它使用$IFS中的字符做分割符而不是步骤1的元字符集;

10、对出现*, ?, [ / ]对执行路径名扩展,也称为通配符扩展;

11、按命令优先级表(跳过别名),进行命令查寻;

12、设置完I/O重定向和其他操作后执行该命令。


二、命令优先级表

1、别名

2、关键字

3、函数

4、内置命令

5、脚本或可执行程序($PATH)


三、关于引用

1、单引号跳过了前10个步骤,不能在单引号里放单引号
2、双引号跳过了步骤1~5,步骤9~10,也就是说,只处理6~8个步骤。

也就是说,双引号忽略了管道字符,别名,~替换,通配符扩展,和通过分隔符分裂成单词。
双引号里的单引号没有作用,但双引号允许参数替换,命令替换和算术表达式求值。可以在双引号里包含双引号,方式是加上转义符"\",还必须转义$,`, \。


四、eval的作用

eval的作用是再次执行命令行处理,也就是说,对一个命令行,执行两次命令行处理。这个命令要用好,就要费一定的功夫。我举两个例子,抛砖引玉。

1、例子1:用eval技巧实现shell的控制结构for

用eval技巧实现shell的控制结构for。

 

[root@home root]# cat myscript1
#!/bin/sh
evalit(){
       if [ $cnt = 1 ];then
               eval $@
               return
       else
               let cnt=cnt-1
               evalit $@
       fi
       eval $@
}
cnt=$1
echo $cnt | egrep "^[1-9][0-9]*$" >/dev/null
if [ $? -eq 0 ]; then
       shift
       evalit $@
else
       echo 'ERROR!!! Check your input!'
fi
[root@home root]# ./myscript1 3 hostname
home
home
home
[root@home root]# ./myscript1 5 id |cut -f 1 -d ' '
uid=0(root)
uid=0(root)
uid=0(root)
uid=0(root)
uid=0(root)

注意:bash里有两个很特殊的变量,它们保存了参数列表。

 

$*,保存了以$IFS指定的分割符所分割的字符串组。
$@,原样保存了参数列表,也就是"$1""$2"...

这里我使用了函数递归以及eval实现了for结构。
当执行eval $@时,它经历了步骤如下:
第1步,分割成eval $@
第6步,扩展$@为hostname
第11步,找到内置命令eval
重复一次命令行处理,第11步,找到hostname命令,执行。

注意:也许有人想当然地认为,何必用eval呢?直接$@来执行命令就可以了嘛。

例子2:一个典型错误的例子

错误!这里给个典型的例子大家看看。

 

[root@home root]# a="id | cut -f 1 -d' '"
[root@home root]# $a
id:无效选项 -- f
请尝试执行‘id --help’来获取更多信息。
[root@home root]# eval $a
uid=0(root)

如果命令行复杂的话(包括管道或者其他字符),直接执行$a字符串的内容就会出错。分析如下。
$a的处理位于第6步──参数扩展,也就是说,跳过了管道分析(第1步),于是"|", "cut", "-f1","-d"都变成了id命令的参数,当然就出错啦。
但使用了eval,它把第一遍命令行处理所得的"id", "|", "cut", "-f1","-d"这些字符串再次进行命令行处理,这次就能正确分析其中的管道了。

 

总而言之:要保证你的命令或脚本设计能正确通过命令行处理,跳过任意一步,都可能造成意料外的错误!

例子3:设置系统的ls色彩显示

 

eval $(dircolors -b/etc/dircolors)

eval语句通知shell接受eval参数,并再次通过命令行处理的所有步骤运行它们。
它使你可以编写脚本随意创建命令字符串,然后把它们传递给shell执行;
$()是命令替换,返回命令的输出字符串。
其中dircolors命令根据/etc/dircolors配置文件生成设置环境变量LS_COLORS的bash代码,内容如下
[root@localhost root]# dircolors -b> tmp
[root@localhost root]# cat tmp
LS_COLORS='no=00:fi=00:di=01;34:ln=01; ......
export LS_COLORS
#这里我没有指定配置文件,所以dircolors按预置数据库生成代码。
其输出被eval命令传递给shell执行。

eval是对Bash Shell命令行处理规则的灵活应用,进而构造"智能"命令实现复杂的功能。
上面提及的命令是eval其中一个很普通的应用,它重复了1次命令行参数传递过程,纯粹地执行命令的命令。
其实它是bash的难点,是高级bash程序员的必修之技。


五、鉴于一些学习中会遇到的困惑,我再给出一些有趣的命令

1、command builtin enable

上面的命令行提及过,第11步会进行命令查找,那它的具体过程如何呢?
它的默认查找次序为函数,内部命令,脚本和可执行代码。我们往往要在实际编程中跳过一些查找项以满足一定的功能需求。这时候就要用到这三个命令来施展魔法~~

2、command

跳过别名和函数的查找,换句话说,它只查找内部命令以及搜索路径中找到的脚本或可执行程序。
这里举个有趣的例子。

 

[root@home root]# type -all pwd
pwd is a shell builtin
pwd is /bin/pwd
[root@home root]# cat myscript2
#!/bin/sh
pwd(){
       echo "This is the current directory."
       command pwd
}
pwd
[root@home root]# ./myscript2
This is the current directory.
/root

 

我用pwd()函数取代了内置命令pwd以及外部命令/bin/pwd,然后在脚本里执行内置命令pwd。在这里我们为什么要用command呢?是为了避免函数陷入递归循环,因为函数名与内置命令同名,而函数的优先级比内置命令高。

3、builtin

顾名思义,它只查找内置命令。这个命令很简单,就不多说了。

4、enable

与builtin相反,它屏蔽一个内置命令,允许运行一个shell脚本或同名的可执行代码而无须给出完全路径名。
举个例子吧。

pwd命令有两个,一个是shell内置的,一个是可执行程序。

当执行一些奇怪的路径名后,shell内置的pwd会打印出"错误信息",但外部的pwd会打印出当前目录的"原来面目"。请看下面:

[root@home root]# cd //
[root@home //]# pwd
//
[root@home //]# type -all pwd
pwd is a shell builtin
pwd is /bin/pwd
[root@home //]# /bin/pwd
/
[root@home //]# enable -n pwd
[root@home //]# pwd
/

 

这样,用enable -n屏蔽内置pwd命令后,就可以用外部pwd打印出正确的路径名了。

Bash博大精深,希望大家好好学习。:)


六、关于本文

本文是home_king兄发在LinuxSir.Org 讨论区的一个专题《【Bas命令行处理】[详解]》,我看这篇文档写的很不错,适用新手,就整理出来了,并对段落进行了相应的排版和格式化,以方便大家阅读;

转自:http://www.linuxsir.org/main/?q=node/134

1. eval command-line

其中commandline是在终端上键入的一条普通命令行。然而当在它前面放上eval时,其结果是shell在执行命令行之前扫描它两次。如:

pipe="|"

eval ls $pipe wc -l

shell1次扫描命令行时,它替换出pipe的值|,接着eval使它再次扫描命令行,这时shell把|作为管道符号了。

如果变量中包含任何需要shell直接在命令行中看到的字符(不是替换的结果),就可以使用eval。命令行结束符(;| &),Io重定向符(< >)和引号就属于对shell具有特殊意义的符号,必须直接出现在命令行中。

2. eval echo \$$# 取得最后一个参数

如:cat last

eval echo \$$#

./last one two three four

four

第一遍扫描后,shell把反斜杠去掉了。当shell再次扫描该行时,它替换了$4的值,并执行echo命令

3.以下示意如何用eval命令创建指向变量的“指针”:

x=100

ptrx=x

eval echo \$$ptrx指向ptrx,用这里的方法可以理解b中的例子

100 打印100

eval $ptrx=5050存到ptrx指向的变量中。

echo $x

50 打印50

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

shell中的eval学习与应用 的相关文章

  • cramfs文件系统制作

    参考 http blog csdn net liukun321 article details 7256456 1 首先配置内核 打开对cramfs的支持 File systems gt Miscellaneous filesystems
  • ubuntu16.04安装cmake-3.8.1最靠谱的方法(ubuntu下安装指定版本cmke)

    1 问题描述 2 cmake安装五种方法 法一 下载cmake二进制安装包 配置路径 亲测有效 法二 cmake源码编译 注意和法一区别 法三 apt安装 法四 在原基础上升级版本 法五 ppa安装 1 问题描述 在配置OpenMVS时 报
  • ubuntu安装ftp服务器( 一般配置 )

    http blog csdn net nation chen article details 7066277 ubuntu安装ftp服务器 1 安装vsftpd sudo apt get install vsftpd ubuntu10 10
  • PF_NETLINK应用实例NETLINK_KOBJECT_UEVENT具体实现--udev实现原理

    相对于linux来说 udev还是一个新事物 然而 尽管它03年才出现 尽管它很低调 J 但它无疑已经成为linux下不可或缺的组件了 udev是什么 它是如何实现的 最近研究Linux设备管理时 花了一些时间去研究udev的实现 udev
  • linux中,如何使用tar进行解压缩

    linux中 如何使用tar进行解压缩 环境 windows 7 virtualboax fedora 15 kde 可以使用tar命令解压缩 tar gz文件 下面以解压缩qt源文件举例 1 在windows中将qt源文件拷贝到共享文件夹
  • Dell工作站8T硬盘安装ubuntu 16.04

    Dell工作站8T硬盘安装ubuntu 16 04 MBR文件系统仅支撑2T磁盘 因此在2T以上磁盘上安装ubuntu时 如果想利用全部磁盘空间 需要采用GPT分区 文件系统 模型 这需要重新分区 制作Ubuntu 16 04启动U盘 一
  • shell命令以及运行原理(详解)

    Linux严格意义上说的是一个操作系统 我们称之为 核心 kernel 但我们一般用户 不能直接使用kernel 而是通过kernel的 外壳 程序 也就是所谓的shell 来与kernel沟通 1 从技术角度 Shell的最简单定义 命令
  • 我使用过的Linux命令之stty - 显示和修改终端行设置

    原文链接 http codingstandards iteye com blog 826924 用途说明 stty命令用于显示和修改终端行设置 change and print terminal line settings 常用参数 stt
  • Linux入坑教程

    服务器安装所需环境 Linux 一 安装基础环境 1 1 JDK 1 2 Mysql 1 3 FastDFS 1 4 Redis 1 5 GIT 1 6 Node 二 Basic commands 基础命令 2 1 查询命令 2 1 1 查
  • Linux下五种I/O模型详解(阻塞IO、非阻塞IO、IO复用、信号驱动、异步IO)

    https blog csdn net gui951753 article details 82348485 感谢博主 我已收藏
  • ssh免密登录,各种权限设置都无效的解决办法!

    如果失败 有可能是以下原因 1 权限问题 这个还得试试 有可能你的权限真的不对 ssh目录 以及 home 当前用户 需要700权限 参考以下操作调整 sudo chmod 700 ssh sudo chmod 700 home 当前用户
  • 臻识车牌识别摄像头对接

    一 臻识车牌识别摄像头 1 非常有用的官方代码 内部有TCP HTTP等协议 2 官方常见问题 3 官方下载专区 二 http对接例子 1 自己使用java mock 模拟后台服务 你会用到的配置文件 java jar moco runne
  • Linux下SUDO出现Unable to resolve host XXX解决方法

    转载 Ubuntu环境 假设这台机器名字叫abc 机器的hostname 每次执行sudo 就出现这个警告讯息 sudo unable to resolve host abc 虽然sudo 还是可以正常执行 但是警告讯息每次都出来 而这只是
  • Linux系统:stress-ng测压工具

    目录 一 理论 1 stress工具简介与安装 2 语法及参数 3 具体安装 二 实验 1 运行8 cpu 4 fork 5 hdd 4 io 50 vm 10小时 2 CPU测试 3 内存测试 4 IO测试 5 磁盘及I O测试 三 问题
  • 理解virt res shr之间的关系 - linux

    转自 https www orchome com 298 想必在linux上写过程序的同学都有分析进程占用多少内存的经历 或者被问到这样的问题 你的程序在运行时占用了多少内存 物理内存 通常我们可以通过top命令查看进程占用了多少内存 这里
  • linux中如何重新configure(或去除已configure的文件)

    linux中如何重新configure 或去除已configure的文件 linux中 在安装源码软件前 需要configure命令来进行安装配置 有时configure后需要重新configure 这时需要进行一些操作 已放置出错 以在f
  • Linux系统下搭建(更新)cuda环境

    本人之前ubuntu系统装的是cuda8 因为模型需要升级cuda 因此重新装cuda10 安装和更新cuda和cudnn以及安装和更新显卡驱动 下面操作都适合 一 安装 升级 显卡驱动 升级cuda之前 先要升级显卡驱动 登陆网页http
  • Linux的目录切换和用户管理

    切换目录 在使用linux系统的时候 会用cd来切换目录 cd 切换到根目录 cd 切换到主目录 cd 切换到之前工作目录 cd 虽然很方便但只能保存一次目录 pushd命令使用目录堆栈可以把多个目录存放起来 配套使用pushd popd
  • spi总线挂载多个设备的设备树描述

    内核版本 linux4 6 Vivado版本 201602 工程中用到很多spi控制的从设备 首先对FPGA工程的正确性验证一下 验证的设备树描述如下 spi e0006000 compatible xlnx zynq spi r1p6 r
  • Linux进程间通信--使用命名管道

    Linux进程间通信 使用命名管道 一 什么是命名管道 命名管道也被称为FIFO文件 它是一种特殊类型的文件 它在文件系统中以文件名的形式存在 但是它的行为却和之前所讲的没有名字的管道 匿名管道 类似 由于Linux中所有的事物都可被视为文

随机推荐

  • VUE-CLI测试环境和打包正式环境的配置切换

    config文件夹pro d env js文件 use strict module exports NODE ENV production API ROOT http 120 79 94 143 配置开发端口 config文件夹dev en
  • 化繁为简,使用Hibernate Validator实现参数校验(一)

    目录 前言 环境配置 导入依赖 基础校验 校验注解 参数绑定 PathVariable RequestParam RequestBody Validated Valid 单参校验 对象校验 分组校验 顺序校验 前言 在之前的悦享校园的开发中
  • docker 离线安装

    目录 服务介绍 软件下载 服务配置 二进制安装docker与docker compose 服务管理命令 服务介绍 docker 是一个供开发和运维人员开发 测试 部署和运行应用的容器平台 docker compose 是一个用于运行和管理多
  • 缓存案例-架构真题(二十二)

    试题一 某大型电商平台建立一个B2B商店系统 并在全国建设了仓储中心 但是在运营过程中 发现很多跨仓储中心调货 延误运送 为此建立全国仓储系统 通过对订单的分析和挖掘 并通过大数据分析预测各类配置 降低成本 当用户通过B2B商店下单 会通过
  • Notepad++ - 缓存目录

    C Users 你的用户名 AppData Roaming Notepad backup 被360清理了 或者程序崩溃了 死机了 都可以在这里找到
  • 华为OD机试经验(A 卷 2022Q4)

    文章目录 1 汇率 2 箱子之字形摆放 3 Excel单元格数值统计 先打个小广告 在我的Hr的指导帮助下 顺利通过了机试 两轮技术面 由于今年顺利研究生上岸 所以没有进行主管面试了 向各位想去华为OD的小伙伴们推荐我的对接Hr微信 蒋虎
  • 【亲测有用】腾讯会议共享PPT,并开启演讲者模式

    出发点 腾讯会议共享PPT 开启演讲者模型 并且观看屏幕的人根本看不到你的演讲者模型 我这边Win10亲测有用 我单笔记本屏幕测试 原理解释 通过播放PPT 产生了一个全屏 可以把它理解为是扩展屏 然后切回演讲者模式的那个屏幕 可以理解为电
  • Redis7--基础篇1(概述,安装、卸载及配置)

    1 Redis概述 1 1 什么是Redis Redis REmote Dictionary Server 远程字典服务器 Remote Dictionary Server 远程字典服务 是完全开源的 使用ANSIC语言编写遵守BSD协议
  • Elasticsearch实战(十三)---聚合搜索Aggs聚合及Count,Avg操作

    Elasticsearch实战 聚合搜索Aggs聚合及Count Avg操作 文章目录 Elasticsearch实战 聚合搜索Aggs聚合及Count Avg操作 1 聚合搜索 bucket 桶及metric分析计算 1 1 准备数据 2
  • vue3+element plus input输入框限制输入数字和小数点

    不能以小数点开头 且只能有一个小数点
  • 如何入门学习python爬虫技术?

    作为一门历史悠久的语言 Python比R更具有通用性 比C 更灵活 可以说Python是一个很全面的语言 尤其是在数据科学 机器学习和AI方面 表现很出色 如果想自学 怎么学习python爬虫技术 一 基础知识的掌握 什么是爬虫 数据是从哪
  • Linux查看内存,线程 ,CPU等情况

    有的时候需要看服务器的状态 比如内存使用状态 线程 CPU使用情况等 要掌握一些linux的命令是很必要的 所以我们大致总结一下这些命令 1 内存使用情况 方法一 top命令 top命令会显示内存 CPU还有swap硬盘等状况 我们可以通过
  • 小知识·CMake使用

    目录 1 cmake 变量引用的方式 2 cmake 自定义变量的方式 3 cmake 常用变量 4 cmake 调用环境变量的方式 5 系统信息 6 主要的开关选项 7 小结 1 cmake 变量引用的方式 使用 进行变量的引用 在 IF
  • Mac修改hosts文件

    hosts可使任意字符串变成一个对应的ip hosts文件位于 private etc hosts 可以通过下面两种方法进行修改 第1种方法 1 终端命令 sudo vi etc hosts 回车后输入密码 再回车就可以打开我们的hosts
  • RTMP开发记录 测试服务器搭建篇

    感谢作者 http www cnblogs com valu p 6287562 html nginx rtmp module 安装 最近在做直播功能 为了方便调试 在本地搭建一个rtmp server吧 我的配置环境是Ubuntu12 0
  • QT 串口通信详解

    1 前言 在进行串口通信时 驱动器或者单片机往往只能发送或接收16进制数据 而对于用户而言 16进制数据显然晦涩难懂 需要将其转换为通俗易懂的10进制或者可读字符串 QT中因为有相关的函数进行转换 特此总结 以加深印象 说明 系统 Wind
  • 【互联网安全】移动APP漏洞风险与解决方案

    移动App是大家使用手机每天接触最多的东西 然而在移动APP开发中 由于一些开发工程师对安全的不重视 导致APP中出现漏洞风险 比如App被逆向 重打包 数据在存储或传输过程中泄露 系统漏洞被利用 逻辑漏洞被绕过等等 本课程 阿里安全专家阿
  • 解决虚拟机挂起重连后无法连接docker容器的问题

    问题描述 最近在docker中部署各种容器时 遇到一个问题 每次挂起虚拟机恢复后 就无法连接docker中的容器了 必须要重新启动容器才能正常连接 非常麻烦 查阅各种资料后 解决方法如下 1 关闭防火墙 由于我是学习环境 所以直接关闭防火墙
  • JavaWeb04(登录&绑值&模糊查询&功能实现&连接数据库)

    目录 一 实现登录功能 2 2 制作简易验证码 2 3 完成登录验证 2 4 登录实现 连接字符串 private static final String URL jdbc oracle thin localhost 1521 orcl 加
  • shell中的eval学习与应用

    http blog csdn net hshl1214 article details 7534589 一 bash命令处理的12个步骤 1 将命令行分成由固定元字符集分隔的记号 SPACE TAB NEWLINE lt gt 记号类型包括