考虑以下 bash 脚本:
#!/bin/bash
echo "${1##*.}"
如果文件名作为第一个命令行参数提供,则此脚本将打印文件的扩展名,如下所示:
$ ./script.sh ./file.pdf
在上面的情况下pdf
被打印。
请解释该表达式如何${1##*.}
提取文件的扩展名。
(我了解 $0、$1、$2、$# 在 bash 中的作用,并且在一定程度上也了解正则表达式)
答案1
Bash 参数扩展支持在扩展变量时可以对值进行多种修改。其中之一是##
,删除值的最长前缀匹配模式(模式是不是正则表达式在这里)。
在本例中,模式是*.
。匹配任何零个或多个字符,后跟.
.${x##*.}
表示删除直到最后一个字符的所有字符串.
,并保留该点之后的所有内容。
${1##*.}
意味着使用第一个位置参数的值进行扩展,您通常使用 访问该参数$1
。最终结果为
echo "${1##*.}"
然后打印出脚本的第一个参数中最后一个参数之后的部分.
,即文件扩展名。
如果图案不完全匹配,变量的完整值将被扩展,就像您没有使用##
.在这种情况下,如果你给出的论点.
根本没有,那么你只需再次将其取回即可。
Bash 还支持使用 single#
来去掉最短的匹配前缀,以及使用相同的方法来%
匹配字符串的末尾。
答案2
简单的例子:
$ A=my.file.name.txt
$ echo ${A}
my.file.name.txt
$ echo ${A#m}
y.file.name.txt
$ echo ${A#my}
.file.name.txt
$ echo ${A#*.}
file.name.txt
$ echo ${A##*.}
txt
在脚本中,${1} 是第一个参数,并且适用相同的概念。
答案3
注意 Bash 参数扩展:
您可以使用 # 运算符从头部修剪字符串
您可以使用 % 运算符从尾部修剪字符串
让我们举个例子:
[my->prompt]$ VAR="head:string:tail"
[my->prompt]$ echo ${VAR##*:} //trim from the head -> till the last ':'
tail
[my->prompt]$ echo ${VAR#*:} //trim from the head -> till the first ':'
string:tail
[my->prompt]$ echo ${VAR%%:*} //trim from the tail <- till the last ':'
head
[my->prompt]$ echo ${VAR%:*} //trim from the tail <- till the first ':'
head:string
[my->prompt]$ VAR2=${VAR%:*} //VAR2="head:string"
[my->prompt]$ echo $VAR2
head:string
[my->prompt]$ echo ${VAR2#*:} //trim from the head -> till the first ':'
string