Shell的强大,很大程度上得益于对命令行做了额外的处理,你可以再命令中嵌入其他命令,在参数中嵌入其他命令,或者嵌入变量,插入路径通配符,插入表达式,Shell都能帮你处理的很好,就因为Shell能做这些,所以Shell才如此强大。
废话少说,直接开始。
首先还是要啰嗦两句,说说Shell处理命令的过程,网上有篇文章写的很不错,很详细,不过我忘记在那儿了,有兴趣的同学可以找找看,用google!我只想说一句:弄清楚Shell处理命令的过程很重要。
简单的说下shell处理命令的过程是:
1.先按<tab> <newline> <space> ( ) < > ; l &把命令分割成一个个的token
2.检查第一个token是不是一个开放的关键字,如for if {等,如果是,说明这是一个复合命令,shell会在内部对关键字进行处理,并重复这一步骤。
3.按别名列表检查每个命令的第一个关键字是不是一个别名,如果是别名,则用其别名定义替换,然后回退到第一步。
4.执行花括号{}扩展
5.执行波浪号~扩展
6.执行变量扩展
7.执行命令替换
8.执行算术表达式计算
9.把生成的新命令按IFS分割成token
10.执行路径扩展
11.按优先级查找命令,先从内置,再从PATH。
12.设定好重定向等,执行命令
过程大致是这样,这里写的很错略,只是为了帮助更好的了解后文。这里要说的就是4,5,6,7,8,10
在Shell中,有六种扩展:花括号、波浪号、变量扩展、命令替换、算术扩展和路径扩展。
花括号扩展:
简单点说就是给一组字符串加上相同的前缀和后缀,生成一组新的字符串。前缀和后缀都可以为空。
[jjz@localhost ~]$ echo a{b,c}d
abd acd
[jjz@localhost ~]$ echo a{b,c}
ab ac
可以使用一个范围,只支持数字和字母。
[jjz@localhost ~]$ echo a{1..10}
a1 a2 a3 a4 a5 a6 a7 a8 a9 a10
[jjz@localhost ~]$ echo a{a..f}
aa ab ac ad ae af
花括号还可以嵌套,逐层有序的进行处理。
[jjz@localhost ~]$ echo a{{1,2},{b,c}}
a1 a2 ab ac
可以认为先生成a{1,2,b,c},然后生成a1 a2 ab ac
要注意的地方:
- 花括号里只有字面量,不要试图使用变量,花括号不支持,比如
[jjz@localhost ~]$ a=1
[jjz@localhost ~]$ echo {$a..10}
{1..10}
并没有生成1 2 3 4 5 6 7 8 9 10。对大括号扩展来说,生成的结果是{$a..10}
,那为什么我们看到的会是{1..10}呢?这就和Shell的命令处理顺序有关了,我们再看看Shell的命令处理顺序,花括号扩展是在第四步,到了第六步,会执行变量扩展,这时候相当于
命令
echo {$a..10}
$a被替换成了1,当然输出的就是{1..10}了。
- 花括号里至少要有一个逗号,也就是至少要有两项
- 两项之间不能有空格,也就是逗号前后不能有空格,否则不进行花括号扩展。
波浪号扩展
波浪号扩展就是对~进行处理。一般情况下,我们认为~代表了自己的主目录,其实事情并非这么简单。进行波浪号替换的条件是很苛刻的。
首先,进行波浪号扩展的前提是波浪号必须位于一个token的开头,简单的说,~前面应该是空格。
然后,shell会分析波浪号之后,第一个/或:之前的未被引号括起来的字符串(如果没有/,那就取波浪号之后的所有字符),这个字符串叫做"波浪号前缀(tilde-prefix)"(注意,所谓波浪号前缀其实是出现在波浪号后面的),波浪号前缀的取值和对应的处理方式是:
- 如果波浪号前缀是个有效用户名,则波浪号和波浪号前缀一起替换成这个用户的主目录
- 如果波浪号前缀为空,则尝试把波浪号替换成HOME,如果HOME没有被设置,则将波浪号替换成当前用户主目录。
- 如果波浪号前缀是+,则~+被替换成当前工作目录(PWD)
- 如果波浪号前缀是-,则~-被替换成上一个工作目录(OLDPWD)
- 如果波浪号前缀是个数字n,则把~n替换成目录堆栈(用dirs命令可以查看目录堆栈)的第n个元素(这个似乎没什么用)
[jjz@localhost ~]$ echo ~
/home/jjz
[jjz@localhost ~]$ echo /~
/~ 波浪号不是在token的开头,不进行扩展
[jjz@localhost ~]$ echo ~root
/root
[jjz@localhost ~]$ echo ~root/
/root/
[jjz@localhost ~]$ echo ~+
/home/jjz 替换成 当前目录
[jjz@localhost ~]$ echo ~-
~- 替换成上一个目录,因为我没用过cd,上一个目录OLDPWD没有设置,所谓替换失败,原样输出
[jjz@localhost ~]$ cd project
[jjz@localhost project]$ echo ~- 这个好了
/home/jjz
[jjz@localhost project]$
变量扩展
这个大家最熟悉了,$foo!$真是个好东西,变量扩展,命令替换,算术扩展都离不了它(当然还能买东西)。一般情况下我们习惯使用$var,其实正规的格式是${var}。前一种形式更简便,后一种更强大,很多时候必须用后一种形式才行。
先说说间接引用,这东西很像C语言里的指针。
${!var},就是左花括号后面紧跟一个感叹号。bash会把变量的值作为新的变量再求值。
[jjz@localhost project]$ a=b
[jjz@localhost project]$ b=1
[jjz@localhost project]$ echo ${!a}
1
其他的操作还是列个表出来,看上去可能更清晰
形式 |
意义 |
${var:-word} |
如果变量var已被设置且非空,则代入它的值,否则带入word |
${var:=word} |
如果变量var已被设置且空,就带入它的值,否则将var设为word并带入var,位置参量不能用这种方式赋值。 |
${var:+word} |
如果var已被设置且值非空,带入word;否则什么都不带入(带入空) |
${var:?word} |
如果var已被设置且值非空,就带入它的值,否则打印word并退出shell。省略word会输出:parameter null or not set |
注意:上面word可以是一个变量,使用$word的形式引用其值
|
${var:offset} |
获取var中offset开始的字串 |
${var:offset:length} |
获取var中offset开始长为length的字串。 |
注意:上面的offset和length可以使变量,使用$offset,$length引用其值
|
${#var} |
替换为变量中字符个数,如果var是* ,@或数组,长度则是位置参量的个数。 |
${var%pattern} |
把字符串尾部与模式进行最小匹配,并删除匹配到的部分。 |
${var%%pattern} |
把字符串尾部与模式进行最大匹配,并删除匹配到的部分。 |
${var#pattern} |
把字符串头部与模式进行最小匹配,并删除匹配到的部分。 |
${var##pattern} |
把字符串头部与模式进行最大匹配,并删除匹配到的部分 |
${var/pattern/string} |
使用string替换pattern的最大匹配部分。如果pattern以/开头则进行全部替换,否则只替换第一个匹配的位置。如果pattern以#开始,则起始部分必须匹配,如果以%开始则结尾部分必须匹配 |
注意:
上面的pattern可以使变量,使用$pattern引用其值。
如果var是*、@或数组且以下标为*或@的形式出现,则对其中每一个元素都进行匹配操作。
|
命令替换
用命令的输出来替换命令本身。有两种形式$(cmd)和`cmd`,推荐前一种形式,后一种形式是old-style了。这个没什么好说的,很简单。
算术扩展
用算术表达式的值替换算术表达式本身。格式$((expr))。expr是个表达式,如4+3。理解起来比较简单。不过关于expression,bash有自己特定的支持,某些运算它是做不了的。
[jjz@localhost project]$ echo $((9+2))
11
[jjz@localhost project]$ b=2
[jjz@localhost project]$ echo $((4+b))
6
[jjz@localhost project]$
路径扩展
shell扫描每个标记看看是否有*,?和[],这三个就是进行路径扩展的。如果某个标记里出现了三者中的一个或几个,这个标记就被认为是一个模式,shell会对当前目录下的文件列表按文件名排序并逐一与此模式进行比较,如果有匹配这个模式的文件,shell用所有能匹配这个模式的文件名列表替换这个模式。如果没有能匹配这个模式的文件,shell原样保留该模式。当然,shell提供了很多选项,定制匹配成功和失败的处理,还可以选择使用高级的正则表达式,这里不进行讨论,只说说shell的默认情况。此处的三个特殊字符也都比较简单*匹配0到多个字符,?匹配一个字符,[]匹配某个区间里一个字符。
分享到:
- 2009-05-16 13:58
- 浏览 3501
- 评论(2)
- 论坛回复 / 浏览 (0 / 5625)
- 查看更多
相关推荐
《Shell脚本专家指南》中的大部分脚本已经在以可靠性为关键因素的生产环境下,经历了多年的不断锤炼和改进。因此,《Shell脚本专家指南》对于那些希望在案头放一本案例精选的读者来说,将会是最佳的参考资料。 这里...
作用地位-比其他语言优势、建立一个规范的shell脚本、执行shell脚本的多种方法及重要区别精讲、shell脚本开发的9点基本规范和习惯、shell的变量-变量类型-全局变量相关知识讲解、shell的特殊变量-难点理论与实战剖析...
第10章bash 脚本编程主讲人: 梁如军本章内容要点Shell 脚本的编制、执行和调试Shell 脚本的成分和编码规范Shell 变量替换扩展、数值计算、输入
通过跳过传统的在命令提示符中输入行的方法,HardLink ShellExtension 似乎是生成这些链接的重要资产。此外,可以通过一个红色图标(可以用自定义图标替换)来轻松区分普通文件和硬链接文件夹(这也适用于路口和符号...
书中的练习和样例脚本中的注释将会与读者进行更好的互动, 但是最关键的前提是: 想真正学习脚本编程的唯一途径就是亲自动手编写脚本. 这本书也可作为教材来讲解一般的编程概念. 本文档的最新版本是作为一个归档...
有关如何使用“ here document”的示例在UNIX shell脚本中,“ here document”的惯用法可以使变量替换更加容易。 这个shell脚本取决于“ here document”表达式。 因此,您可以将其视为如何使用“此处文档”的示例...
特征将具有命令完成功能的“外壳”模式添加到任何Click应用程序大多数点击应用只需更改一行用法只需在根级别命令@click.group @click_shell.shell替换为@click.group @click_shell.shell : import clickfrom click_...
shell高级编程,中英文合集,均为高清版 目录如下: 第一部分. 热身 1. 为什么使用shell 编程 2. 带着一个Sha-Bang 出发(Sha-Bang 指的是#!) 2.1. 调用一个脚本 2.2. 初步的练习 第二部分. 基本 3. 特殊字符 ...
hell 是用户和 Linux 操作系统之间的接口 Linux 中有多种 shell 其中缺省 使用的是 bash Linux 系统的 shell 作为操作系统的外壳为用户提供使用操作系统的接口 它 是一个命令语言解释器 拥有自己内建的 shell 命令集...
例子清单: 2-1. 清除:清除/var/log 下的 log... 在 shell 脚本中调用的窗口部件 34-1. 字符串扩展 34-2. 间接变量引用 - 新方法 34-3. 使用间接变量引用的简单数据库应用 34-4. 用数组和其他的小技巧来处理四人随机打牌
5.shell中删除文件且不显示输出信息和出错信息 58 6.shell变量赋初值时存在特殊字符 58 7.sed的参数串中存在 特殊字符 58 8.find在一个目录下找包含一个字符串的所有文件 58 9.shell中确定一个文件的存在 文件...
书中的练习和样例脚本中的注释将会与读者进行更好的互动, 但是最关键的前提是: 想真正学习脚本编程的唯一途径就是亲自动手编写脚本. 这本书也可作为教材来讲解一般的编程概念. 本文档的最新版本是作为一个归档...
注意: ...此脚本利用mysqldump命令,mysqldump命令是mysql数据库中备份工具,用于将MySQL服务器中的数据库以标准的sql语言的方式导出,并保存到文件中。配合 crontab命令 实现自动备份。 知识扩展 my
和其他Unix shell 一样,它支持文件名替换(通配符匹配)、管道、here文档、命令替换、变量,以及条件判断和循环遍历的结构控制语句。包括关键字、语法在内的基本特性全部是从sh借鉴过来的。其他特性,例如历史命令...
Linux命令shell脚本 参数扩展命令 “^” ”,“ ”#“ ”~“ ”%“ “/” 。^将参数值第一个字符转换成大写,^^将所有字符转换成大写 ,将参数值的第一个字符转换成小写,“ ,,”将所有的字符转换成小写 ~将第一个...
SH Shell解析器,格式化程序和解释器。...该项目利用查找解析器和打印机中的崩溃和挂起。 fuzz-corpus分支包含一个语料库以帮助您入门。 例如: git checkout fuzz-corpus ./fuzz 注意事项 为Bash关
此刻就产生了这样一个问题:使用shell脚本如何批量将所有文件的扩展名JPG都改成小写的jpg? 既然要批量替换文件名,那么肯定得用一个for循环依次遍历指定目录下的每个文件。对于每个文件,假如该文件的名称为name....
3.2 Shell和命令操作基础 3.2.1 Shell简介 3.2.2 命令操作基础 3.2.3 获得命令帮助 3.3 文件概述 3.3.1 什么是文件 3.3.2 文件的类型 3.4 文件与目录操作命令 3.4.1 目录操作命令 3.4.2 文件操作命令 3.4.3 文件打包...