shell中的eval

功能说明:重新运算求出参数的内容。



语  法:eval [参数]



补充说明:eval可读取一连串的参数,然后再依参数本身的特性来执行。



参  数:参数不限数目,彼此之间用分号分开。

1.eval命令将会首先扫描命令行进行所有的替换,憨厚再执行命令。该命令使用于那些一次扫描无法实现其功能的变量。该命令对变量进行两次扫描。这些需要进行两次扫描的变量有时候被称为复杂变量。

2.eval也可以用于回显简单变量,不一定时复杂变量。

NAME=ZONE

eval echo $NAME等价于echo $NAME

3.两次扫描

test.txt内容:hello shell world!

myfile="cat
test.txt"

(1)echo $myfile  #result:cat test.txt

(2)eval echo $myfile  #result:hello shell world!

从(2)可以知道第一次扫描进行了变量替换,第二次扫描执行了该字符串中所包含的命令

4.获得最后一个参数

echo "Last argument is $(eval echo \$$#)"

echo "Last argument is $(eval echo $#)"

shell 也提供了 eval 命令,如同熟悉的其他脚本语言,会将它的参数做为命令执行,初看会疑惑为什么shell要提供两种动态执行命令字串的机制,但是经过仔细分析,才发现shell的eval同其他语言有很大区别。



1.shell 中的函数虽然可以通过return 返回,但是这里的return 相当于 exit,只能是个状态值用于测试,而不能像其它语言一样返回复杂的结果,其处理结果只能通过输出到标准输出经过 `` ,$()取得。



2.shell 中的 eval



    2.1 不能获得函数处理结果 ,如1所说,所有命令,函数的处理结果只能通过 ``来获得,那么其它语言中利用eval来获得动态生成代码执行后的输出变得不可能。



    2.2 eval 嵌套无意义 ,在其他语言中可以通过 eval_r(eval_r("code")),来执行(执行动态生成的code的返回),而由于shell 中 eval 将后面的eval命令简单当作命令字符串执行,失去了嵌套作用,嵌套被命令替换取代。

扩展阅读:eval命令使用示例详解 资料整理www.linuxso.com

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



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



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



[root@home root]# cat myscript1



QUOTE:

#!/bin/sh

evalit(){

        if [ $cnt = 1 ];then

                eval $@

                return

        elee

                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
-f1 -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 -f1 -d' '"

[root@home root]# $a

id:无效选项 #  f

请尝试执行‘id # help’来获取更多信息。

[root@home root]# eval $a

uid=0(root)



如果命令行复杂的话(包括管道或者其他字符),直接执行$a字符串的内容就会出错。分析如下。

$a的处理位于第6步──参数扩展,也就是说,跳过了管道分析,于是"|", "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程序员的必修之技。

linux命令详解——eval的更多相关文章

  1. Linux命令详解之—tail命令

    tail命令也是一个非常常用的文件查看类的命令,今天就为大家介绍下Linux tail命令的用法. 更多Linux命令详情请看:Linux命令速查手册 Linux tail命令主要用来从指定点开始将文 ...

  2. Linux命令详解之—less命令

    Linux下还有一个与more命令非常类似的命令--less命令,相比于more命令,less命令更加灵活强大一些,今天就给大家介绍下Linux下的less命令. 更多Linux命令详情请看:Linu ...

  3. Linux命令详解之—more命令

    Linux more命令同cat命令一样,多用来查看文件内容,本文就为大家介绍下Linux more命令的用法. 更多Linux命令详情请看:Linux命令速查手册 Linux的more命令类似 ca ...

  4. 【转】linux命令详解:md5sum命令

    [转]linux命令详解:md5sum命令 转自:http://blog.itpub.net/29320885/viewspace-1710218/ 前言 在网络传输.设备之间转存.复制大文件等时,可 ...

  5. Linux命令详解之—cat命令

    cat命令的功能是连接文件或标准输入并打印,今天就为大家介绍下Linux中的cat命令. 更多Linux命令详情请看:Linux命令速查手册 Linux 的cat命令通常用来显示文件内容,也可以用来将 ...

  6. Linux命令详解之—pwd命令

    Linux的pwd命令也是一个非常常用的命令,本文为大家介绍下Linux中pwd命令的用法. 更多Linux命令详情请看:Linux命令速查手册 Linux pwd命令用于显示工作目录. 执行pwd指 ...

  7. Linux命令详解之–cd命令

    cd命令是linux实际使用当中另一个非常重要的命令,本文就为大家介绍下Linux中cd命令的用法. 更多Linux命令详情请看:Linux命令速查手册 Linux cd命令用于切换当前工作目录至 d ...

  8. Linux命令详解之–ls命令

    今天开始为大家介绍下Linux中常用的命令,首先给大家介绍下Linux中使用频率最高的命令--ls命令. 更多Linux命令详情请看:Linux命令速查手册 linux ls命令用于显示指定工作目录下 ...

  9. (转)linux命令详解之useradd命令使用方法

    linux命令详解之useradd命令使用方法 原文:http://blog.csdn.net/u011537073/article/details/51987121 Linux 系统是一个多用户多任 ...

随机推荐

  1. Delphi中动态加载TreeView信息

    unit Unit3; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  2. Docker 容器的通信(十二)

    目录 一.容器间通信 1.IP 通信 2.Docker DNS Server 3.joined 容器 二.容器访问外部网络 三.外部网络访问容器 1.随机端口 2.指定端口 3.不指定任何端口. 4. ...

  3. 解决kalilinux:“下列签名无效: KEYEXPIRED 1425567400"

    Kali linux由于太长时间未更新,而出现GPG错误 KEYEXPIRED 1425567400.经检查源未出现问题可以解析,deb也不冲突,就是密钥过期了. 解决方式 使用一条命令,添加新的密钥 ...

  4. laravel 小知识点

    分块导出brokerageCharge = DB::table('表名')$brokerageCharge = $brokerageCharge->chunk(100,function($bro ...

  5. DRF序列化器

    序列化器-Serializer 作用: 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 反序列化,把客户端发送过来的数据,经过request以后变成字典 ...

  6. EOS 资源汇总

    EOS 资源汇总     A curated list of EOS Ecosystem by [SuperONE](https://superone.io/) EOS 主网 超级节点 https:/ ...

  7. Vue 拖拽组件 vuedraggable 、 vue-dragging 、awe-dnd

    参考链接:http://www.ptbird.cn/vue-draggable-dragging.html vue-draggable 学习和使用:https://www.jianshu.com/p/ ...

  8. 我叫Tomcat:一款web服务器

    我叫Tomcat:一款web服务器 如何将我们的 Java 代码,运行在网络上,初学时,首先接触到的一般都是Servlet以及Jsp(或略过Jsp)而 Tomcat 就是这两者的容器,帮你处理动态网页 ...

  9. 【51nod】1407 与与与与

    [51nod]1407 与与与与 设\(f(x)\) 为\(A_{i} \& x == x\)的\(A_{i}\)的个数 设\(g(x)\)为\(x\)里1的个数 \(\sum_{i = 0} ...

  10. Python_Modbus_RTU_通讯Demo

    之前利用Python进行Modbus_TCP进行数据接收,本次需要利用串口进行数据传输,学习Modbus_RTU的简单实现 首先要在创建两个虚拟串口,利用VSPD工具即可.在一台电脑上实现数据的发送和 ...