为什么80%的码农都做不了架构师?>>>
Bash各类扩展详解
Bash中主要包括大括号扩展、波浪号扩展、变量扩展、子命令扩展、文件名扩展和算数扩展。这些扩展组合在一起为Bash带来了极大的易用性。掌握这些扩展的用法和功能,能够为Bash脚本开发带来极大的便捷性,省去很多不必要的操作。同时,这些扩展也是Bash不可或缺的部分,没有了他们Bash可能就是个简单的命令行输入接口而已了。
大括号扩展
大括号扩展主要用于生成随机的字符串,不仅是英语字符,也包括数字。对于数字的大括号扩展在for循环中,有着很重要的用途。大括号扩展的格式有两种,分别为:
- preamble+{string1,string2,...,stringN}+postscript
- preamble+{
.. [.. ]}+postscript
并且大括号扩展是允许嵌套和组合的。
# 第一种形式
echo a{b,c,d,e}f
# abf acf adf aef
# 第二种形式
echo a{b..e}f
# abf acf adf aef
echo a{1..4}f
# a1f a2f a3f a4f
# 组合形式
echo {a,b}{1,2}
# a1 a2 b1 b2
# 嵌套形式
echo {{a..d},{A..D}}
# a b c d A B C D
实例测试结果如下:
波浪号扩展
波浪号扩展主要用于目录匹配,有三种情况,第一种为匹配用户目录,第二种为目录栈中目录,第三种为工作目录。波浪号扩展的基本结构形式为:
~tilde-prefix
其中tilde-prefix的判定规则为,波浪号和斜杠之间的字符都为tilde-prefix,即tilde-prefix的内容在遇到斜杠时结束。在默认情况下,若tilde-prefix没字符处于引号中,则Bash会将tilde-prefix解释为用户名称。如果tilde-prefix为空,则默认使用HOME变量的内容替换,要是HOME变量也没有设置的话,就使用执行当前Bash的用户目录替换。如果tilde-prefix指定的用户不存在的话,则不执行任何替换。
tilde-prefix还有两种比较特殊的情况,分别是加减号和加减号加整数。如果为+号的话,则扩展为PWD变量的值;为-号的号,扩展为OLDPWD变量值。如果是[+,-]integer的形式,则等价于dirs +/-integer。
波浪号扩展的实例如下:
# 匹配用户目录,需要注意的是若存在该用户则执行扩展,若不存在则原样输出
echo ~jackie/Documents
# 存在jackie用户时, /home/jackie/Documents
# 不存在jackie用户时,~jackie/Documents
# 匹配目录栈中目录
# 相当于 dirs +N (N为任意整数), N前可有+或-,如果未设置则默认为+
echo ~+N
# 相当于 dirs +N
echo ~-N
# 相当于 dirs -N
# 匹配当工作目录
echo ~+
# 相当于 ${PWD},若未设置PWD环境变量,则原样输出
echo ~-
# 相当于 ${OLDPWD},若未设置OLDPWD环境变量,则原样输出
实例结果如下:
变量扩展
由于变量扩展中牵扯到很多Bash中的模式匹配,这里将简单的介绍下Bash中的模式匹配。Bash的模式匹配是很简单的,主要就是三个通配符。分别如下:
- => 匹配任意字符串,包括空字符串。
- ? => 匹配任意单个字符。
- [...] => 匹配中括号中指定的任意一个字符。
Bash的模式匹配其实就是上面三个通配符的使用,可以说是正则表达式的简化版。
Bash中的变量匹配形式很多,下面会依次介绍。介绍代码如下:
# ${variable:-word},若variable的值为空或未设置,则扩展结果为word;否则,为variable值。
echo ${str:-abc}
# abc
# ${variable:=word},若variable的值为空或未设置,则将variable置为word,然后扩展结果为variable值。
echo ${str:=abc}
# abc , 使用等号之后abc会赋值给str1变量
# ${variable:?word},若variable的值为空或未设置,则将word值写至标准错误并退出shell;否则,扩展结果为variable值
echo ${str:?abc}
# bash: str: abc,abc会写入stderr
# ${variable:+word},若variable值为空或未设置,则扩展结果为空,否则扩展结果为variable值。
echo ${str:+abc}
# 无任何输出,+号表示,str为空或不存在时,什么不做,否则使用abc
# ${!prefix*}、${!prefix@},扩展为以prefix开头的变量名称。
echo ${!str*}
# 扩展为以str开头的变量
# ${#variable},扩展为variable的字符串长度
echo ${#str}
# 返回str变量的字符长度
str=abcdefghi1234567
# ${variable:offset},获取从offset处到variable值结尾处的字符串
echo ${str:2}
# cdefghi1234567
# ${variable:offset:length},这里offset和length的负数含义和php中的substr相同,或者说跟通常的字符串子串截取一样
echo ${str:2:3}
# cde
# ${variable#word} ${variable##word}
echo ${str#abc}
# defghi1234567
# 在上面这两种形式中,word做为模式都会进行扩展,在扩展完成之后shell会删除该部分,variable中剩余的部分即为结果
# ${variable%word} ${variable%%word}
echo ${str%567}
# abcdefghi1234
# #和%的作用类似,匹配模式word,然后删除并得到结果,区别在于%从variable末尾开始,而#从开始位置开始。
# ${variable/pattern/string}
echo ${str/#abc/jackie}
# jackiedefghi1234567
# 子串替换,符合pattern的字符串替换为string,模式中#好表示从开始位置开始,%表示从结尾位置开始,/表示所有匹配pattern都替换。默认情况下只替换首个匹配pattern的字符串。
# ${variable^pattern} ${variable^^pattern} ${variable,pattern} ${variable,,pattern}
echo ${str^^?}
# ABCDEFGHI1234567
# 大小写转换,^小写至大写,,大写至小写,^和,仅修改首个字符,^^和,,修改每个字符。pattern中不应该包含多个字符
变量扩展实例结果:
子命令扩展
子命令的主要作用是将一个命令的输出替换替换该命令自身,即命令的执行结果作为该命令所在位置的内容。在shell脚本中,子命令大大的提供了各种工具复用的便捷程度。子命令的形式如下:
# 形式一
$(command)
# 形式二
`command`
算数扩展
算数扩展主要用于在Bash中进行简单的计算,格式为 $(( expression )) 。相关事例如下:
echo $(( 5+3 ))
Bash支持所有C语言中的运算符号,下文实例中部分符合运算未列出。且算数扩展是支持相互嵌套的。
具体实例为:
文件名扩展
Bash中路径扩展,实质即为模式匹配,Bash将任何包含*、?和[...]的单词都会进行文件名匹配。例如
# 打印出当前目录下所有以png结尾的文件名,需要注意的是目录也在匹配的范围中,不能简单的以为只匹配文件。
echo *.png
总结
Bash所提供的各种扩展特性,为Bash的日常操作带来了极大的便捷性,不管是运维人员还是各方向的程序开发者,个人认为都应该对其熟练掌握,以提供日常的工作效率。