锁定老帖子 主题:Shell命令中的扩展和替换
精华帖 (4) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
|
||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
作者 | 正文 | |||||||||||||||||||||||||||||
发表时间:2009-05-16
最后修改:2009-07-20
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 要注意的地方:
波浪号扩展 波浪号扩展就是对~进行处理。一般情况下,我们认为~代表了自己的主目录,其实事情并非这么简单。进行波浪号替换的条件是很苛刻的。 首先,进行波浪号扩展的前提是波浪号必须位于一个token的开头,简单的说,~前面应该是空格。 然后,shell会分析波浪号之后,第一个/或:之前的未被引号括起来的字符串(如果没有/,那就取波浪号之后的所有字符),这个字符串叫做"波浪号前缀(tilde-prefix)"(注意,所谓波浪号前缀其实是出现在波浪号后面的),波浪号前缀的取值和对应的处理方式是:
[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 其他的操作还是列个表出来,看上去可能更清晰
命令替换
用命令的输出来替换命令本身。有两种形式$(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到多个字符,?匹配一个字符,[]匹配某个区间里一个字符。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
||||||||||||||||||||||||||||||
返回顶楼 | ||||||||||||||||||||||||||||||
浏览 5675 次