Bash 参数扩展新特性
bash 手册页接近 4 万字。它虽然不像战争与和平那么长,但在廉价小说书架上也能占有一席之地。鉴于 bash 文档的篇幅,在查看手册页时很容易错过有用的功能。因此,为了寻找新功能,偶尔重温手册页可能是有益的。
今天感兴趣的小节是参数扩展——即,$var的多种形式。不过,不要被这个名称所迷惑,它实际上是关于参数和变量扩展。
我不会在这里介绍参数扩展的所有不同形式,只介绍一些我认为可能不如其他形式广为人知的形式。如果您完全不熟悉参数扩展,请查看我很久以前的文章或互联网上其他地方的许多文章之一。
使用以下命令将字符串转换为大写的日子已经一去不复返了tr '[[:lower:]]' '[[:upper:]]'将字符串转换为大写
$ a=hello
$ echo ${a^} # First character only
Hello
$ echo ${a^^} # All characters
HELLO
以及转换为小写
$ a=HELLO
$ echo ${a,} # First character only
hELLO
$ echo ${a,,} # All characters
hello
您还可以在 operator 之后指定一个字符,并且只更改匹配字符的大小写
$ a=hello
$ echo ${a^l} # First character if it is an 'l'
hello
$ echo ${a^^ll} # All characters that are 'l's
heLLo
需要变量名与特定前缀匹配的所有变量的列表吗?这样做
$ mya=1
$ myb=2
$ yourc=3
$ echo ${!my*}
mya myb
Bash 甚至可以让您体验到 C 和汇编编程以及使用间接寻址的美好旧时光——好吧,有点像
$ var=somevalue
$ var_name=var
$ echo ${!var_name}
somevalue
这里发生的事情是var_name的值为您提供了要扩展的实际变量的名称。然后扩展该变量并成为扩展的结果。在本例中,“var_name”的值为“var”,因此变量“var”被扩展以产生最终值“somevalue”。
作为一个题外话,因为它实际上与“参数扩展”无关,让我们快速了解一下 bash 中的命名引用。命名引用变量是一个引用另一个变量的变量
$ var=no
$ declare -n ref=var # -n == nameref
$ ref=yes
$ echo $ref
yes
变量“ref”是对变量“var”的引用。当您赋值给“ref”时,实际上更改了“var”的值。这在通过将变量名称传递给函数来从函数中获取值时特别方便
$ cat nref.sh
function func()
{
local -n up_value=$1 # -n == nameref
up_value=new_value
echo "Changing '${!up_value}' in ${FUNCNAME[0]}"
}
aval=old_value
echo
echo "Before function call, aval is $aval"
func aval # pass var *name* to func
echo "After function call, aval is $aval"
运行该命令,您会得到
$ bash nref.sh
Before function call, aval is old_value
Changing 'aval' in func
After function call, aval is new_value
由于命名引用变量是自动间接引用的,因此您无需使用感叹号扩展来获取被引用变量的值;正常的$var扩展即可。在命名引用的情况下,感叹号扩展会产生不同的结果:被引用变量的名称。因此,这个小小的题外话毕竟还是与参数扩展有关。
还有许多形式为${var@?}的扩展,其中“?”是字母“Q”、“E”、“P”、“A”或“a”之一,可以转换值或获取有关变量本身的信息。例如
$ declare -a array=(1 2)
$ echo Attributes: ${array@a}
Attributes: a # i.e. array was declared with -a
查看手册页以获取有关这些“@”扩展的更多信息。
最后总结一下,在阅读参数扩展部分时,另一个容易被忽略的细微之处与许多扩展中的冒号(:)有关。例如,:-形式的扩展允许在变量未设置或为空时指定默认值
unset var
$ echo var: ${var:-default}
var: default
var=
$ echo var: ${var:-default}
var: default
现在,如果您省略冒号
unset var
$ echo var: ${var-default}
var: default
var=
$ echo var: ${var-default}
var:
因此,省略冒号会将测试从“未设置或空”更改为仅测试“未设置”。这适用于:-, :=, :?和:+形式的参数扩展。
如果某些功能似乎不起作用,请检查您的 bash 版本
$ echo $BASH_VERSION
4.4.23(1)-release