shell 中变量的替换
${value:-word}
当变量未定义或者值为空时,返回值为 word 的内容,否则返回变量的值。
# 变量a未定义返回了123
$ echo ${a:-123}
123
# 定义变量 a=10,返回 10
$ a=10 && echo ${a:-123}
10
${value:=word}
与前者类似,只是若变量未定义或者值为空时,在返回 word 的值的同时将 word 赋值给 value。
# 变量 b 未定义,返回 20 并把值赋给 b
$ echo ${b:=20}
20
# 可以看到,现在变量 b 的值为 20
$ echo $b
20
${value:?message}
若变量已赋值的话,正常输出变量的值。否则将消息 message 送到标准错误输出(若此替换出现在 Shell 程序中,那么该程序将终止运行)。
# c 变量没有定义就会终止程序并输出后面设置好的提示信息
$ echo ${c:?变量未定义或者未赋值}
-bash: c: 变量未定义或者未赋值
# 变量定义了,就会输出变量的值
$ c=10 && echo ${c:?变量未定义或者未赋值}
10
${value:+word}
若变量已赋值的话,其值才用 word 替换,否则不进行任何替换。
# 可以看到变量 d 未赋值没有进行替换
$ echo ${d:+12}
# 给变量 d 赋值后进行了替换
$ d=10 && echo ${d:+12}
12
${value:offset}
${value:offset:length}
从变量中提取子串,这里 offset 和 length 可以是算术表达式,offset 代表偏移量,从第几个字符开始提取,length是需要提取的字符串的个数。
# 从第 3 个字符后面开始提取 2 个字符
$ e=abcdefghijk && echo ${e:3:2}
de
# 从第 5 个字符后面开始提取 6 个字符
$ e=abcdefghijk && echo ${e:5:6}
fghijk
${#value}
变量的字符个数
# 计算变量 f 的字符个数
$ f=abcde && echo ${#f}
5
${value#pattern}
和 ${value##pattern}
去掉 value 中与 pattern 相匹配的部分,条件是 value 的开头与 pattern 相匹配。# 与 ## 的区别在于一个是最短匹配模式,一个是最长匹配模式。
$ g="hehello heworld" && echo ${g##he}
hello heworld
$ g="hehello heworld" && echo ${g#he}
hello heworld
$ g="hehello heworld" && echo ${g##heworld}
hehello heworld
实验证明 ${value#pattern}
和 ${value##pattern}
没有太大区别,都只能从开头匹配,而且都只能匹配一次。
${value%pattern}
和 ${value%%pattern}
和上面的例 7 类似,只是是从 value 的尾部和 pattern 相匹配。% 与 %% 的区别跟 # 与 ## 一样。
$ h="hehello heworld" && echo ${g%heworld}
hehello
$ h="hehello heworld" && echo ${g%he}
hehello heworld
$ h="hehello heworld" && echo ${g%%he}
hehello heworld
$ h="hehello heworld" && echo ${g%%ld}
hehello hewor
实验证明${value%pattern}
和${value%%pattern}
没有太大区别,都只能从结尾匹配,而且都只能匹配一次。
${value/pattern/string}
和 ${value//pattern/string}
进行变量内容的替换,把与 pattern 匹配的部分替换为 string 的内容,’/’ 与 ’//’ 的区别是 ’/’ 只进行一次匹配替换,而 ’//’ 可以进行多次匹配替换。
$ i="hello world" && echo ${i/wo/aa} #这里把wo替换成为aa
hello aarld
$ i="hello world" && echo ${i/o/b} #这里把一个o替换成为b
hellb world
$ i="hello world" && echo ${i//o/b} #这里把两个o都替换成为b
hellb wbrld