运行顺序和eval

shell从标准输入或脚本中读取的每一行称为管道,它包括了一个或多个命令,这些命令被一个或多个管道字符(|)隔开.

其实嗨哟非常多特殊符号可用来切割单个的命令:分号(;),管道(|),&,逻辑AND(&&),逻辑OR(||).对于每个地区的管道,shell都会将命令切割,为管道设置I/O,而且对每个命令依次运行以下的操作.

看起来非常复杂,可是每一个步骤都是在shell的内存里发生的,shell不会真的把每一个步骤的发生演示给我们看.所以这是我们分析shell内存的情况,从而知道每一个阶段的命令行是怎样被转换的.

案例:

mkdir /tmp/x #建立暂时性文件夹

cd /tmp/x #切换到该文件夹

touch f1 f2 #建立文件

f=f y=”a b” #赋值两个变量

echo ~+/${f}[12] $y $(echo cmd subst) $((3+2))>out      #忙碌的命令

上述命令的运行步骤:

1.命令一開始会依据shell语法而切割为token.最重要的一点是:I/O重定向>out在这里是被识别的,并存储供稍后使用.流程继续处理以下这行,当中每一个token的范围显示于命令下方的行上:

echo ~+/${f}[12] $y $(echo cmd subst) $((3 + 2))

| 1 | |----- 2 ----| |3 | |-------- 4----------| |----5-----|

2.坚持第一个单词(echo)是否为keyword,比如if或for.在这里不是,所以命令行不变继续运行.

3.坚持第一个单词(依旧是echo)是否为别名.这里不是,所以命令行不变继续处理.

4.扫描全部单词是否须要波浪号展开.在这里~+等同于$PWD,也就是当前文件夹.token2将被改动,处理继续例如以下:

echo /tmp/x/${f}[12] $y $(echo cmd subst) $((3 + 2))

| 1 | |------- 2 -------| |3 | |-------- 4----------| |----5-----|

5.变量展开:token2与3都被改动.产生:

echo /tmp/x/${f}[12] a b $(echo cmd subst) $((3 + 2))

| 1 | |------- 2 -------| | 3 | |-------- 4----------| |----5-----|

6.处理命令替换.注意,这里可递归引用列表里的全部步骤!在此例中,由于我们要试图让全部的东西easy理解,因此命令改动了token4,结果:

echo /tmp/x/${f}[12] a b cmd subst $((3 + 2))

| 1 | |------- 2 -------| | 3 | |--- 4 ----| |----5-----|

7.运行算术替换 .改动token5,结果:

echo /tmp/x/${f}[12] a b cmd subst 5

| 1 | |------- 2 -------| | 3 | |--- 4 ----| |5|

8.前面全部的展开产生的结果,都将再一次被扫描,看看是否有$IFS字符.假设有,则他们是作为分隔符,产生额外的单词.比如,两个字符$y原来是组成一个单词,但展开式”a空格b”,在此阶段被切分为两个单词:a与b.同样方式也应用于命令替换$(echo cmd subst)的结果上.先前的token3变成了token3与4.先前的token4则成了token5与6.结果:

echo /tmp/x/${f}[12] a b cmd subst 5

| 1 | |------- 2 -------| 3 4 |-5-| |- 6 -| 7

9.通配符展开.token2变成了token2与token3:

echo /tmp/x/$f1 /tmp/x/$f2 a b cmd subst 5

| 1 | |---- 2 ----| |---- 3 ----| 4 5 |-6-| |- 7 -| 8

10.这时,shell已经准备好了要运行最后的命令了,他会去寻找echo.正好ksh93与bash的echo都内建到shell中了

11.shell实际运行命令.首先运行>out的I/O重定向,在调用内部的echo版本号,显示最后的參数.

最后的结果:

$cat out

/tmp/x/f1 /tmp/x/f2 a b cmd subst 5

eval语句

shell中的eval这个命令非常奇妙,他能把字符串当做命令来运行.PS:这个字符串必须是可运行的bash命令才干够.

案例:

eval “ls” #输出当前文件夹的全部文件

语法: eval [參数]

补充说明:eval可读取一连串的參数,然后再依慘呼本身的特性来运行.

參数:不限数目,彼此之间用分号隔开.

案例:我有一个文件test.txt

命令:cat test.txt

输出:hello world

命令:myfile="cat test.txt"

命令:echo $myfile

输出:cat test.txt

命令:eval $myfile

输出:hello world

从eval $myfile这条命令能够看出,eval进行了变量替换,将字符串中属于bash的命令运行了.

把拼接起来的字符串当作命令运行,这就是eval的奇妙之处.

subShell与代码块

subShell是一群被括在圆括号中的命令,这些命令会在另外的进程中运行.当你须要让一小组的命令在不同的文件夹下运行时,这样的方式能够让你不必改动主脚本的文件夹,直接处理这样的情况.

比如:tar -cf -.| (cd /tmp;tar -xpf -)

左边的tar命令会产生当前文件夹的tar打包文件,将他传送给标准输出.这份打包文件会通过管道传递给走遍的subShell里的命令.开头的cd命令会先切换到新文件夹,也就是让大宝文件在此文件夹下解开.然后,走遍的tar将从打包文件里解开文件.注意,运行此管道的shell(或脚本)并未更改他的文件夹.

代码块概念上与subShell雷同,仅仅只是他不会建立新的进程.代码块里的命令以花括号({})括起来,且对主脚本的状态会造成影响(比如他的当前文件夹).一般来说,花括号被视为shellkeyword,意即他们仅仅有出如今命令的第一个符号时会被识别.实际上:这表示你必须将结束花括号放置在换行字符或分号之后.比如:

cd /home/directory||{

echo could not change to /home/directory!>&2

echo you lose !>&2

exit1

}

IO重定向也能够套用subShell与代码块里.在该情况下,全部的命令会从重定向来源读取它们的输入或传送他们的输出.

subShell与代码块

结构

定界符

认可的位置

另外的进程

SubShell

()

行上的不论什么位置

是

代码块

{}

在换行字符,分号或keyword之后

否

注意:代码块里的exit会终止整个脚本.

我们通常在shell中执行一个脚本仅仅须要简单的调用./[script_name]就可以,这样的方式下,shell会启动一个子进程来执行该脚本,称为subShell,当subShell执行完毕,子进程结束.父进程的环境不会有不论什么改变.

案例:bash代码

#!/bin/bash

cd /var/cache

testname="fine"

分别在shell中执行

1.  ./test.sh;echo $testname  会发现还是位于原来的文件夹中,$testname的值书粗话为null.

2. source ./test.sh;echo $testname这里就不一样了,如今你位于/var/cache中,$testname的值也变成了fine

用source命令来执行脚本,不会产生子进程,脚本在shell的进程空间中执行,所以执行重定义的变量,执行的操作,都会在shell的执行环境中保留下来.

shell学习三十八天----运行顺序和eval的更多相关文章

  1. shell学习五十八天----/proc文件系统

    /proc文件系统 前言:linux中的/proc文件系统,由一组文件夹和文件组成,挂载(mount)与/proc文件夹下. /proc文件系统是一种虚拟文件系统,以文件系统文件夹和文件形式,提供一个 ...

  2. shell学习三十七天----引用

    引用 案例,假设我想输出一个星号(*),使用echo怎样做? echo * 这是肯定不行的,须要将*转移,即:echo \* 这样就引出了引用的概念.所为引用,是用来防止shell将某些你想要的东西解 ...

  3. python学习三十八天常用内置函数分类汇总

    python给我们提供丰富的内置函数,不用去写函数体,直接调用就可以运行,很方便快速给我提供开发所需要的函数. 1,查内存地址 id() 变量的内存地址 id() 2,输入输出 input()  pr ...

  4. linux shell学习三

    Shell for循环 Shell for循环的语法如下所示 for 变量 in 列表 do command1 command2 ... commandN done 举例: ..} do echo $ ...

  5. Struts2学习三----------Action搜索顺序

    © 版权声明:本文为博主原创文章,转载请注明出处 Struts2的Action的搜索顺序 http://localhost:8080/path1/path2/student.action 1)判断pa ...

  6. shell学习三十四天----printf详解

    http://blog.csdn.net/shanyongxu/article/details/46744055

  7. shell学习四十八天----文件校验和匹配

    文件校验和匹配 要是你怀疑可能有非常多文件具有同样的内文,而是用cmp或diff进行比較全部横队的比較,导致所花费的时间会随着文件数目增长成次方的增长. 这是能够使用file checksum(文件校 ...

  8. PHP语言学习之php-fpm 三种运行模式

    本文主要向大家介绍了PHP语言学习之php-fpm 三种运行模式,通过具体的内容向大家展示,希望对大家学习php语言有所帮助. php-fpm配置 配置文件:php-fpm.conf 开启慢日志功能的 ...

  9. Shell学习之环境变量配置文件(三)

    Shell学习之环境变量配置文件 目录 环境变量配置文件简介 环境变量配置文件作用 其他配置文件和登录信息 环境变量配置文件简介 环境变量配置文件简介 环境变量配置文件中主要是定义对系统操作环境生效的 ...

随机推荐

  1. Oracle 临时表空间 temp表空间切换

    一.TEMP表空间 临时表空间主要用途是在数据库进行排序运算.管理索引.访问视图等操作时提供临时的运算空间,当运算完成之后系统会自动清理.当oracle里需要用到sort的时候,PGA中sort_ar ...

  2. 算法笔记_159:算法提高 第二大整数(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 编写一个程序,读入一组整数(不超过20个),当用户输入0时,表示输入结束.然后程序将从这组整数中,把第二大的那个整数找出来,并把它打印出来 ...

  3. eclipse 编译JAVA 项目导入的WEB项目 无法编译问题

    右击你的项目 选择properties  ---->java Build Path--->Default output folder新建一个classes目录就好了 watermark/2 ...

  4. sql查询备份或还原等操作的大概完成时间

    查询出来的还需完成时间还算比较准确 --查询备份或还原等操作的大概完成时间 select command ,percent_complete ,running_time))+' hour, ' ))+ ...

  5. 【VBA编程】12.Workbook对象常用属性

    [ActiveSheet属性] ActiveSheet属性用于返回一个对象,表示活动工作簿中或指定的窗口或工作簿中的活动工作表 [Colors] Colors属性是一个Variant类型的可读写属性, ...

  6. Hadoop系统通信协议介绍(转)

    转载自 ---- http://weilaiyxj.iteye.com/blog/913166 本文约定: DN: DataNode TT: TaskTracker NN: NameNode SNN: ...

  7. iOS-格式化金额,三位一逗号

    代码地址如下:http://www.demodashi.com/demo/11244.html 项目版本更新迭代中, 新增需求: 所有金额必须用标准会计表示方式(¥94,862.57). 而之前金额展 ...

  8. Cacti监控MySQL实现过程中碰到的问题解汇总

    前言:cacti监控mysql服务器的大概50张graphs都弄出来了,也出图了,当中遇到一些问题,印象比較深刻的记录例如以下: (一):加入io监控 点击Create Graphs for this ...

  9. java基础讲解02-----eclipse快捷方式(2017-04-12 23:47)

    ctrl  + shift+o  出去多余的引用包     ctrl+i   修改格式        

  10. 用GDB命令PO(print-object)打印UIView的视图层级

    UIView有一个私有方法: recursiveDescription 这个方法可以显示出当前视图的详细层级,可以在代码中直接调用,也可以在GDB中调用,在GDB中调用时需要借助另一个GDB命令:pr ...