Shell参数扩展
摘自:Bash 参考手册
字符"$“引导参数扩展,命令替换和算术扩展。将要扩展的变量名或符号可以放在大括号中。大括号虽然是可选的,但却可以保护待扩展的变量,使得紧跟在大括号后面的部分名称不会被扩展。如果使用了大括号,则与这匹配的结束半边是第一个没有用反斜杠转义或不属于引用字符串的”}",这个结束符不能嵌入在算术扩展、命令替换、或者参数扩展之中。参数扩展的基本形式是
${参数}
结果用参数的值替换。如果参数是包含多个数位的位置参数,或者参数后面的字符不应该当成是整个名称的一部分,则大括号是必须的。如果参数的第一个字符是个感叹号,就表示某个级别的间接变量。Bash使用后续变量的值作为新变量的名称,然后扩展这个新的变量,并用其值进行替换,而不是后续变量的值。这叫做间接扩展。下面将介绍的${!前缀*}
和${!名称[@]}
属于例外情况。感叹号必须紧跟在大括号后面才表示间接变量在很多其它语言中,可以用$$A
来表示以$A
为名称的间接变量,而Bash中不可以,即使 ${$A}
也不可以;Bash只识别感叹号形式的间接变量。不过,这个功能在其它的shell中可能没有。所以,为了增强可移植性,可以这样写:
eval echo \$$B
在下面介绍的每种情况中,名称都要进行波浪号扩展、参数扩展、命令替换和算术扩展。如果不是进行字符串扩展,使用下面的形式时,Bash会检查参数是否已经设置或者为空;只有当参数尚未设置时才会在测试时忽略冒号后面的结果。换句话说,如果包含了冒号,则这个运算符会测试参数是否存在,同时还会检查它是否为空;如果忽略了冒号,就只检查变量参数是否存在。
${参数:−单词}
如果参数没有设置或者为空,则替换为单词;否则替换为参数的值。
${参数:=单词}
如果参数没有设置或者为空,则把扩展后的单词赋给参数,然后替换为参数的值。对位置参数和特殊参数,不可以这样进行赋值。
${参数:?单词}
如果参数没有设置或者为空,就把扩展后的单词(如果没有给出单词,则代之以一条大意相同的相信)写到标准错误输出中。如果当前的shell是交互式的,退出shell。否则,替换为参数的值。
${参数:+单词}
如果参数没有设置或者为空,不进行任何替换;否则,替换为扩展后的单词。
${参数:偏移量}
${参数:偏移量:长度}
扩展为参数中从偏移量开始的不超过长度个字符。如果没有指定长度,扩展为参数中从偏移量开始的子字符串。长度和偏移量都是算术表达式。这又叫做"子字符串扩展"。
长度的值必须是个大于或等于零的数字。如果长度的值是个小于零的数,它就会被当成参数所表示的字符串中从结尾开始的偏移量。如果参数是"@
",结果就是从偏移量开始的第长度个位置参数。如果参数是带有"@
“或”*
“下标的下标数组名,则结果是该数组中从${参数[偏移量]}
始的长度个元素。负的偏移量是从数组中比最大的下标大一的数字开始的。对键值数组进行子字符串扩展的结果没有定义。注意,负数的偏移量与冒号之间至少得有一个空格,这样可以避免与”:-
"扩展相混淆。
查找子字符串的下标是从0开始的;但是如果使用了位置参数,则默认从1开始。如果使用位置参数时偏移量是0,则把 $@添加到结果前面。
${!前缀*}
${!前缀@}
扩展为名称中含有前缀的变量,以特殊变量 IFS 的第一个字符分隔。如果使用了"@
",并且在双引号内扩展,则每个变量都扩展成单独的单词。
${!名称@}
${!名称*}
如果名称是个数组变量,扩展成名称内数组下标或者键名列表。如果名称不是数组变量,则如果名称已经设置就扩展为 0,否则扩展为空值。如果使用了"@
",并且在双引号内扩展,则每个键或下标都扩展成单独的单词。
${#参数}
替换为参数扩展后所含的字符数目。如果参数是"*
“或”@
",则替换为位置参数的个数。如果参数是带有下标"*
“或”@
“的数组名,则在做的为该数组中元素的个数。
${参数#单词}
${参数##单词}
单词被扩展成一个模式,就像文件名扩展一样。如果这个模式与参数扩展后的值开始部分匹配,则替换的结果是该模式与参数扩展后的值最短的匹配部分(指”#
")或者最长的匹配部分(指"##
")删除以后的字符串。如果参数是"*
“或”@
",则模式删除操作就对位置参数依次进行,扩展的结果就是所得到的位置参数列表。如果参数是带有下标"*
“或”@
"的数组名,则模式删除操作就对数组元素依次进行,扩展的结果就是所得到的数组元素列表。
${参数%单词}
${参数%%单词}
单词被扩展成一个模式,就像文件名扩展一样。如果这个模式与参数扩展后的值开始部分匹配,则替换的结果是该模式与参数扩展后的值最短的匹配部分(指"%
")或者最长的匹配部分(指"%%
")删除以后的字符串。如果参数是"*
“或”@
",则模式删除操作就对位置参数依次进行,扩展的结果就是所得到的位置参数列表。如果参数是带有下标"*
“或”@
“的数组名,则模式删除操作就对数组元素依次进行,扩展的结果就是所得到的数组元素列表。
${参数/模式/字符串}
模式被扩展成一个模式,就像文件名扩展一样。参数被扩展后,与模式匹配的最长部分用字符串来取代。如果模式以”/
“开头,则所有与之匹配的部分都用字符串来取代,而通常情况下,只取代第一个匹配的部分。如果模式以”#
“开头,它就只能和参数扩展后的开始部分匹配。如果模式以”%
“开头,它就只能和参数扩展后的结尾部分匹配。如果字符串为空,则与模式匹配的部分将被删除;这时,模式后面的 /
也可以省略。如果参数是带有下标”*
“或”@
"的数组名,则模式删除操作就对数组元素依次进行,扩展的结果就是所得到的数组元素列表。
${参数^模式}
${参数^^模式}
${参数,模式}
${参数,,模式}
这种扩展会改变参数中字母符号的大小写。模式被扩展成一个模式,就像文件名扩展一样。运算符"^
“把匹配部分的小写字母转换为大写;运算符”,
“把匹配部分的大写字母转换为小写。”^^
“和”,,
“扩展转换参数扩展后的每个匹配的字符,而”^
“和”,
“扩展只转换参数扩展后第一个匹配的字符。如果省略了模式,则它则当成”?",这就与每个字符都匹配。如果参数是"*
“或”@
",则大小写转换操作就对位置参数依次进行,扩展的结果就是所得到的位置参数列表。如果参数是带有下标"*
“或”@
"的数组名,则模式删除操作就对数组元素依次进行,扩展的结果就是所得到的数组元素列表。