10.3. 变量的操作

10.3.1. 变量的算术运算

我们在第 3.4.6 节中已经讨论过这个问题。

10.3.2. 变量的长度

使用 ${#VAR} 语法将计算变量中的字符数。如果VAR"*""@",则此值将替换为位置参数的数量或一般情况下数组中元素的数量。这在下面的示例中演示。

[bob in ~] echo $SHELL
/bin/bash

[bob in ~] echo ${#SHELL}
9

[bob in ~] ARRAY=(one two three)

[bob in ~] echo ${#ARRAY}
3

10.3.3. 变量的转换

10.3.3.1. 替换

${VAR:-WORD}

如果VAR未定义或为空,则替换为WORD的扩展;否则,替换为VAR的值

[bob in ~] echo ${TEST:-test}
test

[bob in ~] echo $TEST
 

[bob in ~] export TEST=a_string

[bob in ~] echo ${TEST:-test}
a_string

[bob in ~] echo ${TEST2:-$TEST}
a_string

这种形式常用于条件测试,例如在下面的例子中

[ -z "${COLUMNS:-}" ] && COLUMNS=80

它是以下内容的简写形式

if [ -z "${COLUMNS:-}" ]; then
	COLUMNS=80
fi

有关此类条件测试的更多信息,请参阅第 7.1.2.3 节

如果连字符 (-) 替换为等号 (=),则当参数不存在时,该值将被赋值给参数

[bob in ~] echo $TEST2


[bob in ~] echo ${TEST2:=$TEST}
a_string

[bob in ~] echo $TEST2
a_string

以下语法测试变量是否存在。如果未设置,则将WORD的扩展打印到标准输出,并且非交互式 shell 退出。一个演示:

[bob in ~] cat vartest.sh
#!/bin/bash
 
# This script tests whether a variable is set.  If not,
# it exits printing a message.
 
echo ${TESTVAR:?"There's so much I still wanted to do..."}
echo "TESTVAR is set, we can proceed."

[bob in testdir] ./vartest.sh
./vartest.sh: line 6: TESTVAR: There's so much I still wanted to do...

[bob in testdir] export TESTVAR=present

[bob in testdir] ./vartest.sh
present
TESTVAR is set, we can proceed.

使用 "+" 而不是感叹号会将变量设置为WORD的扩展;如果它不存在,则什么也不会发生。

10.3.3.2. 删除子字符串

要从变量中剥离等于OFFSET的字符数,请使用以下语法

${VAR:OFFSET:LENGTH}

参数LENGTH定义了从偏移点之后的第一个字符开始保留多少个字符。如果LENGTH被省略,则取变量内容的其余部分

[bob in ~] export STRING="thisisaverylongname"

[bob in ~] echo ${STRING:4}
isaverylongname

[bob in ~] echo ${STRING:6:5}
avery

${VAR#WORD}

${VAR##WORD}

这些构造用于删除与WORDVAR. WORD的扩展相匹配的模式,就像在文件名扩展中一样。如果模式与VAR的扩展值的开头匹配,则扩展的结果是VAR的扩展值,其中包含最短匹配模式 ("#") 或最长匹配模式(用 "##" 表示)。

如果VAR*@,则模式删除操作将依次应用于每个位置参数,并且扩展是结果列表。

如果VAR是使用 "*""@" 下标的数组变量,则模式删除操作将依次应用于数组的每个成员,并且扩展是结果列表。如下面的示例所示。

[bob in ~] echo ${ARRAY[*]}
one two one three one four

[bob in ~] echo ${ARRAY[*]#one}
two three four

[bob in ~] echo ${ARRAY[*]#t}
one wo one hree one four

[bob in ~] echo ${ARRAY[*]#t*}
one wo one hree one four

[bob in ~] echo ${ARRAY[*]##t*}
one one one four

使用 "%""%%" 可以获得相反的效果,如下面的示例所示。WORD应该匹配字符串

[bob in ~] echo $STRING
thisisaverylongname

[bob in ~] echo ${STRING%name}
thisisaverylong

10.3.3.3. 替换变量名称的一部分

这是使用

${VAR/PATTERN/STRING}

${VAR//PATTERN/STRING}

语法完成的。第一种形式仅替换第一个匹配项,第二种形式替换所有匹配项,将PATTERN替换为STRING:

[bob in ~] echo ${STRING/name/string}
thisisaverylongstring

更多信息可以在 Bash info 页面中找到。