Shell脚本支持七种类型的扩展功能:花括号扩展(brace expansion)、波浪号扩展(tilde expansion)、参数与变量替换(parameter and variableexpansion)、命令替换(command substitution)、算术扩展(arithmeticexpansion)、单词切割(word splitting)和路径替换(pathnameexpansion)
1、花括号扩展,不可以使用引号
jichengwei@localhost ~ % echo {a,bf,d} a bf d jichengwei@localhost ~ % echo {a..z} a b c d e f g h i j k l m n o p q r s t u v w x y z jichengwei@localhost ~ % echo {1..9..2} 1 3 5 7 9 jichengwei@localhost ~ % echo t{a,e}p tap tep
2、波浪号
波浪号在Shell脚本中默认代表当前用户的家目录,我们也可以在波浪号后面跟一个有效的账户登录名称,可以返回特定账户的家目录。但是,注意账户必须是系统中的有效账户。
显示当前用户的家目录
jichengwei@localhost ~ % echo ~
/Users/jichengwei
波浪号扩展中使用~+表示当前工作目录,~-则表示前一个工作目录。
3、变量替换
在Shell脚本中我们会频繁地使用$对变量进行扩展替换,变量字符可以放到花括号中,这样可以防止需要扩展的变量字符与其他不需要扩展的字符混淆。如果$后面是位置变量且多于一个数字,必须使用{},如$1、${11}、${12}。
如果变量字符串前面使用感叹号(!),可以实现对变量的间接引用,而不是返回变量本身的值。感叹号必须放在花括号里面,且仅能实现对变量的一层间接引用。
变量替换操作还可以测试变量是否存在及是否为空,若变量不存在或为空,则可以为变量设置一个默认值。
jichengwei@localhost ~ % echo ${ani:-dogs} dogs jichengwei@localhost ~ % echo $ani jichengwei@localhost ~ % echo ${ani2:=dogs} dogs jichengwei@localhost ~ % echo $ani2 dogs jichengwei@localhost ~ % echo ${an3:?'error'} zsh: an3: 'error' jichengwei@localhost ~ % an4=123 jichengwei@localhost ~ % echo ${an4:+lock} lock jichengwei@localhost ~ % echo $an4 123
字符串切割与掐头去尾具体语法
[root@VM-42-19-centos ~]# home="The oak tree, It was covered with yeelo handkerchiefs." [root@VM-42-19-centos ~]# echo ${home:2} e oak tree, It was covered with yeelo handkerchiefs. [root@VM-42-19-centos ~]# echo ${home:14:6} It was [root@VM-42-19-centos ~]# echo ${home#Th} e oak tree, It was covered with yeelo handkerchiefs. [root@VM-42-19-centos ~]# echo ${home#The} oak tree, It was covered with yeelo handkerchiefs. [root@VM-42-19-centos ~]# echo ${home#*y} eelo handkerchiefs. 最短匹配,将匹配到的第一个o前面的都删掉 [root@VM-42-19-centos ~]# echo ${home#*o} ak tree, It was covered with yeelo handkerchiefs. 最长匹配,将匹配到的最后一个o和前面的都删掉 [root@VM-42-19-centos ~]# echo ${home##*o} handkerchiefs. 从右往左删除 [root@VM-42-19-centos ~]# echo ${home%efs.} The oak tree, It was covered with yeelo handkerchi [root@VM-42-19-centos ~]# echo ${home%d*} The oak tree, It was covered with yeelo han [root@VM-42-19-centos ~]# echo ${home%%d*} The oak tree, It was covere 这些扩展对数据也生效 [root@VM-42-19-centos ~]# tools=(car helicoper airplane train) [root@VM-42-19-centos ~]# echo ${tools[0]} car [root@VM-42-19-centos ~]# echo ${tools[0]#c} ar
变量内容的统计与替换
4、命令替换
我们可以通过$(命令)或者`命令`实现命令替换,推荐使用$(命令)这种方式,该方式支持嵌套的命令替换。
echo "系统当前登录人数:$(who|wc -l)"
5、算术替换
算术替换扩展的格式为$(()),也可以使用$[]的形式,算术扩展支持嵌套。 [root@VM-42-19-centos ~]# echo $((i++)) [root@VM-42-19-centos ~]# echo $((2**3)) [root@VM-42-19-centos ~]# echo $((20/5)) [root@VM-42-19-centos ~]# echo $((3==4)) [root@VM-42-19-centos ~]# echo $((3!=4))
6、进程替换
命令替换将一个命令的输出结果返回并且赋值给变量,而进程替换则将进程的返回结果通过命名管道的方式传递给另一个进程。
进程替换的语法格式为:<(命令)或者>(命令)。一旦使用了进程替换功能,系统将会在/dev/fd/目录下创建文件描述符文件,通过该文件描述符将进程的输出结果传递给其他进程。
root@VM-42-19-centos ~]# who|wc -l 1 [root@VM-42-19-centos ~]# wc -l <(who) 1 /dev/fd/63 [root@VM-42-19-centos ~]# ls /dev/fd/63 ls: cannot access /dev/fd/63: No such file or directory
通过匿名管道(|)我们可以将一个命令的输出结果传递给另一个进程作为其输入的内容,上面的示例中who | wc -l的目的就是通过匿名管道统计当前系统登录人数。相同的功能我们还可以使用进程替换的方式来实现。<(who)会将who命令产生的结果保存到/dev/fd/63这个文件描述符中,并将该文件描述符作为wc -l命令的输入参数,最终wc -l <(who)的输出结果说明了在/dev/fd/63这个文件中包含5行内容。需要注意的是,文件描述符是实时动态生成的,所以当进程执行完毕,再使用ls查看该文件描述符时会提示没有该文件。
提取/etc/passwd文件中的账户名称(第一列)和家目录(第六列),再提取/etc/shadow中的密码信息(第二列),最后通过paste命令将数据合并为一个文件信息,paste命令会逐行读取多个文件的内容并将多个文件合并。
[root@VM-42-19-centos ~]# paste <(cut -d: -f1,6 /etc/passwd) <(cut -d: -f2 /etc/shadow)
[root@VM-42-19-centos 123]# touch {a,b,c}.sh [root@VM-42-19-centos 123]# touch {11,22,33}.conf [root@VM-42-19-centos 123]# ls |tee >(grep sh$ >sh.1.log) >(grep conf$ >conf.log) 11.conf 22.conf 33.conf a.sh b.sh conf.log c.sh sh.1.log
7、单词切割
单词切割也叫分词,Shell使用IFS变量进行分词处理,默认使用IFS变量的值作为分隔符,对输入数据进分词处理后再执行命令。如果没有自定义IFS,则默认值为空格、Tab制表符和换行符。
8、路径替换
除非使用set -f禁用路径替换,否则Bash会在路径和文件名中搜索*、?和[符号,如果找到了这些符号则进行模式匹配的替换,Shell在处理命令时对路径替换后的路径或文件进行处理。如果使用shopt命令时开启了nocaseglob选项,则Bash在进行模式匹配时不区分大小写,默认是区别大小写的。另外,还可以在使用shopt命令时开启extglob选项,可以让Bash支持扩展通配符。shopt命令的-s选项可以开启特定的Shell属性,-u选项可以关闭特定的Shell属性。
[root@VM-42-19-centos 123]# dirname /root/123/11.conf /root/123 [root@VM-42-19-centos 123]# basename /root/123/11.conf 11.conf
参考:shell核心编程