bash 变量引用扩展
我们都知道,在bash
中,若定义了一个变量x=3
,则使用${x}
来进行变量替换 ,将x
的值替换为3
,在bash
中,为变量替换提供了非常多的功能,下面我们一一来看下:
为不存在的变量赋默认值:
当引用一个不存在的变量的时候,默认会替换为空,比如,当没有定义x
这个变量,直接使用它的时候,其结果会为空,案例如下:
bash
#!/bin/bash
# 未定义变量x直接使用
echo x: ${x}
上述脚本执行的结果为:
bash
# bash var_declaration.sh
x:
#
在bash
中,可以在变量后添加:=
而后是该变量的默认值,这样的话,如果没有定义该变量,那么该变量的默认值则为新的值,比如:
bash
#!/bin/bash
# 未定义变量x直接使用
echo x: ${x:=123}
echo x: ${x}
其执行结果为:
bash
# bash var_declaration.sh
x: 123
x: 123
#
如上赋予默认值更多使用在接收命令行参数,用户可能并未输入参数,需要给定一个默认值的情况来执行,这样便可以直接进行if
判断,而非提前判断是否为空了,脚本如下:
bash
#!/bin/bash
operation=$1
echo 执行的选项为:${operation:=none}
if [ ${operation} = "yes" ];then
echo "yes!!!"
fi
上述脚本,operation
的值来源于命令行的第一个参数,如果并没有输入具体的参数,则使用默认值none
,而后进行参数判断,如果假设没有给定默认值,那么在进行if
字符串判断的时候,没有值和yes
字符串做比对,会报错:[: =: unary operator expected
。
为不存在的变量赋临时值:
上述是为了不存在的变量给定了默认值,若在变量中添加-
则表示赋予临时默认值,使用后即失效,例如:
bash
#!/bin/bash
echo a: ${a:-5}
echo a: ${a}
上述脚本并没有定义变量a
,但是在第一个echo
语句的时候,将其变量替换为了5
,此时并未重新定义a
这个变量,所以第二个echo
的时候,会输出为空,其结果为:
bash
# bash var_declaration.sh
a: 5
a:
#
这种方式适用于仅判断一次的的脚本,比如,可以将上述脚本修改为这样的:
bash
#!/bin/bash
operation=$1
if [ ${operation:-none} = "yes" ];then
echo "yes!!!"
fi
这样,若operation
为空的话,那么参数只在if
判断中被赋予none
的值,而后依然为空。
为不存在的变量抛错
在工具类脚本中,需要有非常强的健壮性,若某些关键配置缺失,需要报错并且退出脚本,以往我们的做法是直接进行判断,若不存在再exit
非标准退出,比如下面这个脚本片段:
bash
#!/bin/bash
# x未被定义
if [ -z ${x} ];then
echo 错误:x未被定义
exit 1
fi
上述脚本的含义为:若当x
未被定义的时候,使用-z
进行判断,-z
的意思是后面待判断的值为空,则抛错,x
未被定义,或者定义了为空,然后使用exit
退出程序。
若要判断数十个或者数百个变量,即使使用函数的形式,也有大量的代码,其实在bash
中,也为我们提供了类似的功能,比如下面语句可以完全代替上述语句块:
bash
#!/bin/bash
# x未被定义
${x:?x未被定义或者为空}
echo "456"
直接使用:?
关键字来判断,当x
未被定义的时候,就对后面语句进行错误输出。且中断程序执行,直接退出,退出状态码为1。执行后结果为:
bash
# bash var_declaration.sh
var_declaration.sh: line 4: x: x未被定义或者为空
# echo $?
1
#
上述结果,当判断x
未被定义的时候,就进行预定义的错误输出,且退出程序,不会执行后续语句,最后的退出状态码为1
。效果和上述使用if
来判断一致(上述使用if
判断是标准输出,这里是错误输出)。
字符串切片
在bash
中,可以对字符串进行切片处理,其用法为:
bash
${待处理的字符串变量:偏移量[:长度]}
其中,长度部分是可选的;如果不写长度的话,则默认会截取到字符串的末尾。
当偏移量小于0
的时候,默认会从第 0
位开始截取;若当长度为负数时,则表示从字符串末尾向前回退相应的字符数来进行截取。
这里需要注意的时,字符串起始是0
,而非1
。
案例如下:
bash
x="abcedf"
echo ${x:0}
上述代码表示x
的值为abcedf
,输出的时候,设置偏移量为0
,长度没有写,则默认长度,所以最后输出的结果为:
bash
abcedf
若想截图3个字符,则只需将长度设置为3
即可:
bash
x="abcedf"
echo ${x:0:3}
上述代码的结果为:
bash
abc
从想直接截取到最后的2个字符前,只需要将长度设置为-2
即可,例如:
bash
x="abcedf"
echo ${x:0:-2}
其结果为:
bash
abce
若调整了偏移量,假设为2,则表示从第二位开始截取,截取的长度由后面的参数来决定,比如:
bash
x="abcedf"
echo ${x:1:3}
上面代码表示从字符串的第1
位开始截取,截取的长度为3
。
字符串匹配删除
在bash
中,不仅可以对字符串进行切片,还能进行匹配删除,匹配可以分为惰性匹配和贪婪匹配,当然在bash
中称为是最短匹配 和最长匹配。
字符串匹配删除的语法为:
bash
${待处理的字符串变量#最短删除规则}
${待处理的字符串变量##最长删除规则}
这里所指的规则可以是普通字符串,也可以是匹配模式。这个匹配模式,不同于正则表达式,这里暂时不做讲述。回到字符串匹配删除这里来。
比如有如下字符串:
bash
x=dabcabcabcef
比如想要删除abc
,可以这样使用:
bash
x=dabcabcabcef
echo ${x#*abc}
echo ${x##*abc}
上述删除规则为*abc
,其中*
表示匹配任意个字符,对于字符串dabcabcabcef
而言,*abc
可以匹配为abc
字符串本身,也可以匹配为dabc
,也可以匹配为dabcabcabc
,只要是出现abc
的,前面都可以被匹配到。
所以最短匹配删除的语句是${x#*abc}
,对于dabcabcabcef
字符串而言,*abc
表示从开头开始,匹配到第一个出现的abc
字符串,即:dabc
。
而对于最长匹配删除的语句是${x##*abc}
,对于字符串dabcabcabcef
而言,*abc
表示从开头开始,匹配到最后一个abc
字符串,即:dabcabcabc
。
所以,该脚本执行的结果为:
bash
# bash var_declaration.sh
abcabcef
ef
#
总结
在bash
中,已经为我们提供了变量提供了很多的操作,包括判断变量是否已经赋值,为不存在的变量抛错等,提供了字符串切片,匹配删除等,无需自己亲自动手实现,只需要调用语法,便可以轻松完成这些步骤,当然bash
变量引用扩展还不止如此,由于篇幅有限,就介绍到这里,剩下的后面有机会再详细介绍。