闲着无聊,对着Bash官网整理了一下Bash参数扩展相关的内容
前置知识
IFS
IFS为shell的分割符,默认为” \t\n”(space,tab和换行符),当他们出现在字符串开头和结尾时将被忽略,只有存在在字符串中间时才起到分割符作用,如果$IFS被设为null时,将不会对字符进行分割。
特殊参数
如果尚未了解IFS
请先参阅IFS
$* 和 $@ 都表示传递给函数或脚本的所有参数,当它们不被双引号" "
包含时,都以”$1” “$2” … “$n” 的形式输出所有参数。但是当它们被双引号" "
包含时,”$*” 会将所有的参数作为一个整体,以”$1 $2 … $n”的形式输出所有参数;”$@” 则会将各个参数分开,以”$1” “$2” … “$n” 的形式输出所有参数,而他们正是以IFS
进行分隔。
1 | $ cat a;./a 1 2 3 4 |
格式 | 含义 |
---|---|
$0 |
当前脚本的文件名 |
$n |
传递给脚本的参数。n 为数字,表示第几个参数,当n大于9时参数必须使用大括号。例 ${10} |
$# |
传递给脚本或函数的参数个数 |
$? |
上个命令的退出状态,或函数的返回值。一般情况下,命令执行成功返回0,执行失败返回1 |
$$ |
当前Shell的PID |
$_ |
上一个执行命令的最后一个参数 |
$! |
上一个进程的PID,前提是上一个进程还在后台运行着,要不然你会像我一样好奇,为什么不输出呢 |
${!#} |
传入脚本的最后一个参数 |
$'\nnn' |
字符串扩展,\nnn为8进制值 |
Bash参数扩展
空参数处理
格式 | 描述 |
---|---|
${parameter:-word} |
当变量未初始化或为空时,用word将其替换,否则输出原有变量值 |
${parameter:+word} |
当变量不为空时,用word将其替换 |
${parameter:=word} |
当变量未初始化或为空时,用word将其替换,并将word赋值给$parameter |
${parameter:?word} |
当变量未初始化或为空时,将报错 |
1 |
|
子串截取
格式 | 描述 |
---|---|
${parameter:offset} |
从offset处开始,截取到结尾 |
${parameter:offset:length} |
从offset处开始,截取length长度的子串 |
offset可以为负数,表示从尾部开始数。当offset为负数时,:
和-
之间至少要隔一个空格,否则会被解释成:-
执行,就是上面那个${parameter:-word}
length也可以是负数,表示从offset截取到从尾部向前偏移length绝对值个的位置。
1 |
|
另外,子串截取还存在着几种特殊形式
格式 | 描述 |
---|---|
${n:offset} |
${n}表示第n个参数 对那个参数进行截取 |
${n:offset:length} |
对第n个参数从offset开始截取length个 |
${@:offset} |
${@}表示传递给函数或脚本的所有参数,截取结果为offset位置开始的参数直到最后 |
${@:offset:length} |
从offset位置开始的参数,截取length个 |
1 |
|
间接展开
如果还不了解$*
与$@
的区别,请先参阅$*和$@
格式 | 描述 |
---|---|
${!prefix} |
扩展为 变量名为变量prefix的值 的值 |
${!prefix*} |
扩展为以prefix为前缀的所有变量名 |
${!prefix@} |
扩展为以prefix为前缀的所有变量名,不同之处参阅$*和$@ |
${!name[*]} |
扩展为name数组元素的下标,如果name则扩展为0 |
${!name[@]} |
不同参阅$*和$@ |
1 |
|
参数长度
格式 | 描述 |
---|---|
${#parameter} |
替换为变量parameter的值的长度 |
1 |
|
匹配删除
格式 | 描述 |
---|---|
${parameter#word} |
最小限度从前面截取word, |
${parameter##word} |
最大限度从前面截取word |
${parameter%word} |
最小限度从后面截取word |
${parameter%%word} |
最大限度从后面截取word |
其实上面所说的最大、最小,就类似于正则表达式中的“贪婪”和“懒惰”
1 |
|
字符串替换
格式 | 描述 |
---|---|
${parameter/pattern/string} |
将parameter里第一个pattern替换成string |
${parameter//pattern/string} |
将parameter里所有pattern替换成string |
${parameter/#pattern/string} |
将parameter头部的pattern替换成string |
${parameter/%pattern/string} |
将parameter尾部的pattern替换成string |
1 |
|
大小写替换
格式 | 描述 |
---|---|
${parameter^pattern} |
当paremeter头部有pattern,将pattern部分改为大写 |
${parameter^^pattern} |
将parameter中所有pattern改为大写 |
${parameter,pattern} |
当paremeter头部有pattern,将pattern部分改为小写 |
${parameter,,pattern} |
将parameter中所有pattern改为小写 |
1 |
|
参数转换
此扩展为bash4.4的新增特性
格式 | 含义 |
---|---|
${parameter@operator} |
根据不同的operator,对parameter进行相应处理,operator共有五种值 |
Q | 此operator功能是给parameter值加上合适的引号,使其成为可重用的字符串形式 |
E | 当parameter值为转义字符时,可以将其解义 |
P | 将parameter值按prompt字符含义进行转义,prompt含义请参阅官方文档 |
A | 将parameter值和它名字一起,转换为赋值语句形式,如有任何的属性,也将转换出 |
a | 获取 parameter 的所有属性 |
1 |
|
同样此扩展可以作用于数组。但当数组带有[*]和[@]下标时,如果operator是QEPa中一个时,则对数组每一个元素进行扩展,之后返回的值是以列表的形式。不过当operator为A时,返回的是一个用declare声明数组形式的字符串。
1 |
|
另外一提,至少在2020.4.3前,此扩展用法在zsh上无效
虽然上面的大多数扩展,完全可以以sed
、awk
、cut
、perl
等来实现,但参数扩展为bash内置,速度更快。