在bash中,通常使用${parameter}表达式来获取参数变量的值,这就是参数展开(parameterexpansion).Bash还提供了其他形式的参数扩展,可以对变量值做一些处理,起到操作字符串的作用。例如:${parameter#word}删除参数变量值开头的部分匹配词,保留剩余内容。${parameter%word}从参数变量值的末尾往前删除部分匹配词,保留前面剩余内容。注意:这些表达式都不会修改参数本身的变量值,它们只是根据参数的变量值展开得到一个新的值。如果要保存这些值,则需要将它们分配给特定的变量。有关说明,请参阅manbash的参数扩展部分。具体例子如下。${parameter#word}和${parameter##word}见manbash对${parameter#word}和${parameter##word}的说明如下:Romovematchingprefixpattern。这项工作被扩展以产生一个模式,就像在路径名扩展中一样。如果模式与参数值的开头匹配,则扩展的结果是删除最短匹配模式('#'大小写)或最长匹配模式('##'大小写)的扩展参数值.如果参数是@或*,模式删除操作依次应用于每个位置参数,扩展是结果列表。如果参数是一个用@或*订阅的数组变量,则模式删除操作依次应用于数组的每个成员,展开是结果列表。即${parameter#word}从头开始匹配参数变量值中wordpattern对应的内容。如果有匹配,则删除最短的匹配并返回变量的其余部分。后面会举例说明,方便理解。而${parameter##word}在参数变量值中,从头开始匹配wordpattern对应的内容。如果存在匹配项,则删除最长的匹配项并返回变量的其余部分。上面提到的“最短匹配”和“最长匹配”主要是针对多条匹配的情况。如果参数变量的值中有多处匹配单词pattern,“最短匹配”的意思是在第一个匹配的地方停止匹配,返回其余的。“最长匹配”将匹配到最后一个匹配,然后返回其余匹配。这里的单词模式可以使用通配符进行扩展,但不能使用正则表达式。注意:上面所说的“从头开始匹配”是指从头开始比较参数变量值和单词pattern,而不是任意匹配参数变量值中的单词pattern。具体例子如下:$value="This/is/a/test/string"$echo${value#This}/is/a/test/string$echo${value#test}This/is/a/test/string$echo${value#*test}/string上面定义了一个value变量,然后获取${value#This}的值。这个参数扩展的意思是匹配value变量值中从头开始的“This”字符串。如果匹配,则删除“This”字符串并返回值变量的其余部分。它在此处匹配,因此删除了“This”字符串并打印了“/is/a/test/string”。但是echo${value#test}的打印结果和value变量值完全一样。即不匹配中间的“test”字符串,最短匹配为空,不删除任何字符串。使用${value#*test}匹配value变量value中间的“test”字符串,删除所有匹配的内容,打印“/string”。这里*通配符用来匹配“test”之前的任意字符,从而匹配value变量值的开头。注意:${parameter##word}是操作参数变量值,不是“参数”字符串。所以如果要过滤一个字符串的内容,需要先把这个字符串赋值给一个变量,然后用变量名扩展参数。将字符串内容直接写在花括号{}里面是不行的,即使字符串被引号括起来了。具体例子如下:$echo${This/is/a/test/string#This}#执行不会报错,但是输出为空$echo${"This/is/a/test/string"#This}#添加引号会执行错误-bash:${"This/is/a/test/string"#This}:badsubstitution$echo${'This/is/a/test/string'#This}-bash:${'This/is/a/test/string'#This}:badsubstitution如你所见,这里的四个表达式都不能直接处理字符串本身的内容。${parameter##word}的用法和${parameter#word}类似,也是删除匹配的内容,返回剩余的内容。不同之处在于${parameter#word}在匹配到第一个时停止。而${parameter##word}是匹配到最后一个才停止。以上面的值变量为例,具体说明如下:$echo${value#*is}/is/a/test/string$echo${value##*is}/a/test/stringcan可以看出,echo${value##*is}打印“/is/a/test/string”。给定的*is匹配字符串“This”,不匹配后面的“is”字符串,所以只删除“This”字符串。echo${value##*is}打印“/a/test/string”。它先匹配“This”,然后继续匹配,最后匹配的是“is”字符串,所以删除“This/is”字符串。还是那句话,上面说的“匹配”是从头匹配,不是部分匹配。要求字模展开后得到的字符串从一开始就符合参数变量值的内容,而不是在参数变量值中寻找字模。例如下面的例子:$value="This/is/a/test/string./This/is/a/new/test"$echo${value##*This}/is/a/new/test.$echo${value##This}/is/a/test/string./This/is/a/new/test可以看到value变量有两个“This”字符串。echo${value##*This}匹配最后一个“This”字符串。但是echo${value##This}仍然只匹配开头的“This”字符串。它不是在值变量值中寻找“This”子串,而是从头开始逐个字符地匹配“This”字符串和值变量值。在echo${value##*This}表达式中,*This是通配符扩展的,value变量value中有多种匹配形式。比如从头匹配到“This”字符串,匹配到“This/is/a/test/string./This”字符串。去掉最长匹配后,打印为“/is/a/new/test.”。注意区别。注意:在bash的参数扩展中,数字属于位置参数,数字可以用来指代传递给脚本或函数的参数。在当前表达式中使用时,表示对传入的参数值进行处理。比如$1对应传入的第一个参数,那么${1##pattern}表示匹配传入的第一个参数值中的patternpattern并处理。具体例子如下:$functionparam_tail(){echo${1##*test};}$param_tail"这是一个测试字符串。"字符串。您可以看到param_tail函数使用${1##*test}来匹配输入的第一个参数中的“test”字符串及其前面的任何字符。如果可以匹配,则去掉匹配的内容,只保留后面的部分。如果给定的参数是数组变量,给定的下标是@或*,则对每个数组元素进行匹配删除,最终展开的结果是一个合成列表。当需要对多个字符串进行相同的处理时,可以将它们放入一个数组中,然后使用这两个表达式进行处理。以下示例从多个文件路径中过滤掉单个文件名,删除目录路径部分:$arrays=("src/lib/utils.c""src/main/main.c""include/lib/utils.h")$echo${arrays[@]##*/}utils.cmain.cutils.h可以看出,${arrays[@]##*/}表达式使用arrays[@]来指定操作每个元素数组数组。使用*/匹配目录路径中的/字符,该字符前面可以有任意数量的其他字符。使用##指定最长匹配,会匹配到最后一个/字符。最终,表达式删除匹配的部分并返回剩下的部分,即文件名本身。${parameter%word}和${parameter%%word}见manbash对${parameter%word}和${parameter%%word}的说明如下:去除匹配后缀模式。这个词被扩展以产生一个模式,就像在路径名扩展中一样。如果模式与参数扩展值的尾部匹配,则扩展的结果是具有最短匹配模式('%'情况)或最长匹配模式('%%'情况)的参数扩展值)删除。如果参数是@或*,模式删除操作依次应用于每个位置参数,扩展是结果列表。如果parameter是一个下标为@或*的数组变量,则模式移除操作依次应用于数组的每个成员,扩展为结果列表。即${parameter%word}匹配参数变量值的后缀部分,从后往前匹配单词模式对应的内容。如果有匹配,则删除最短的匹配并返回变量的其余部分。所谓“最短匹配”,就是从参数变量值的末尾开始,从后往前匹配,一旦匹配到就结束匹配。后面会举例说明,方便理解。而${parameter%%word}匹配参数变量值的后缀部分,从后往前匹配单词模式对应的内容。如果存在匹配项,则删除最长的匹配项并返回变量的其余部分。所谓“最长匹配”,就是从参数变量值的末尾开始,从后往前匹配,一直匹配到最后一个匹配。这里的单词模式可以使用通配符进行扩展,但不能使用正则表达式。上面解释的${parameter#word}是从变量值中删除匹配的前缀部分,保留其余内容。相反,${parameter%word}从变量值中删除匹配的后缀部分,保留剩余的内容。具体例子如下:$value="This/is/a/test/string./This/is/a/new/test"$echo${value%test}This/is/a/test/string./这个/is/a/new/$echo${value%%test}This/is/a/test/string./This/is/a/new/$echo${value%%test*}This/is/a/$echo${value%is*}This/is/a/test/string./This/$echo${value#*is}/is/a/test/string./This/is/a/new/test可以看到${value%test}在value变量value中从后往前匹配“test”字符串,删除匹配到的内容,得到前面剩下的部分。${value%%test}获得与${value%%test}相同的值。因为表达式是从末尾逐字匹配的,所以它不会匹配到第二个“test”字符串,只会匹配最后的“test”字符串。如果要匹配第二个“测试”字符串,可以使用*通配符。${value%%test*}表示从后往前匹配,直到最后一个“test”模式不停。由于${parameter%word}表达式是从后往前匹配的,所以必须在wordpattern后面写*通配符才能匹配中间的内容。如${value%is*}的输出所示。而${parameter#word}是从前到后匹配的,所以*通配符必须写在wordpattern的前面才能匹配到中间的内容。如${value#*is}的输出所示。
