当涉及到命令行工具和脚本编写时,Shell变量是一个非常重要的概念。利用Shell变量的一些奇妙用法,我们可以用一个简单的表达式实现复杂操作,使我们的命令更加简洁高效。
本文将介绍一些常用的Shell变量操作符,包括字符串操作、数组操作等。这些操作符可以帮助我们快速地截取子字符串、替换文本、遍历数组等操作。本文所有用法适用于bash,部分适用于ksh。
变量子串
${var} 返回变量var的内容,单独使用时有没有{}一样,混合多个变量和常量时,用{}界定变量名
${#var} 返回变量var内容的长度
${var:offset} 从变量var中的偏移量offset开始截取到字符串结尾的子字符串,offset从0开始
${var:offset:length} 从变量var中的偏移量offset开始截取长度为length的子字符串
${var#*.} 从变量var中删除第一个匹配的点(.)及其左边的所有字符
${var##*.} 从变量var中删除最后一个匹配的点(.)及其左边的所有字符
${var%.*} 从变量var中删除最后一个匹配的点(.)及其右边的所有字符
${var%%.*} 从变量var中删除第一个匹配的点(.)及其右边的所有字符
示例:
var=file.txt.tar.gz
${var#*.} #内容为"txt.tar.gz"
${var##*.} #内容为"gz"
${var%.*} #内容为"file.txt.tar"
${var%%.*} #内容为"file"
也可以使用其它Pattern和表达式,示例:
var=/home/xxx/aaa/file.txt #假设xxx为当前用户
# 从路径中获取文件名
${var##*/} #内容为"file.txt"
# 将绝对路径转为相对路径
# whoami是获取当前用户名,使用$()执行子shell,$(whoami)将得到xxx
~${var#*$(whoami)} #内容为"~/aaa/file.txt"
${var/pattern/string} 使用string代替第一个匹配的pattern
${var//pattern/string} 使用string代替所有匹配的pattern
${var,} 首字母转小写
${var,,} 全部转小写
${var^} 首字母转大写
${var^^} 全部转大写
特殊扩展变量
${var-word} 如果变量var未赋值,则返回字符串word
${var:-word} 如果变量var未赋值或者值为空,则返回字符串word
${var+word} 如果变量var有值(包括空串""),则返回字符串word
var1=foo
var2=
${var1-word} # 内容为"foo"
echo ${var2-word} # 内容为""
echo ${var2:-word} # 内容为"word"
${var:+word} 如果变量var有值且不为空,则返回字符串word
${var=word} 如果变量var未赋值,则返回字符串word,并为var赋值为字符串word
${var:=word} 如果变量var未赋值或者值为空串,则返回字符串word,并为var赋值为字符串word
${var?word} 如果变量var未赋值,将字符串word作为标准错误输出,否则返回变量var的值
${var:?word} 如果变量var未赋值或者值为空串,将字符串word作为标准错误输出,否则返回变量var的值
数组
array=(1 2 3 a b c) 定义一个名为array的数组,包含了6个元素,元素字段类型不需要统一
${array[index]} 访问数组中的元素,index从0开始,如果为负表示从数组的末尾开始的偏移量
${array[*]} 获取数组中所有元素
${array[@]} 获取数组中所有元素
${#array[*]} 获取数组的长度
${#array[@]} 获取数组的长度
${!array[@]} 获取数组索引列表,返回 0 1 2 3 4 5
array+=(4 d) 向数组中添加元素,数组内容为 1 2 3 a b c 4 d
unset array[6] 删除第 7 个元素,数组内容为 1 2 3 a b c d
unset array[-1] 删除倒数第 1 个元素,数组内容为 1 2 3 a b c
多行字符串变量
var=$(cat <<- 'EOF'
line1
line2
...
EOF
)
或者使用单引号或者双引号(单引号中${}和$()等都不会取表达式的值,双引号中才会):
var='line1
line2
...'
注意上述两种写法的差别,避免为变量内容带来不必要的空行。通过循环可依次得到变量中的每一行:
while read -r line; do
echo $line
done <<< $var
Shell系统变量
$1 表示第一个参数,$2 表示第二个参数 ...
$# 命令行参数的个数
$0 当前Shell脚本程序的名称
$? 前一个命令或函数的返回码
$* 以 "参数1 参数2 ... " 形式获取所有参数
$@ 以 "参数1" "参数2" ... 形式获取所有参数
$$ 本程序的进程ID,即PID
$! 上一个命令的PID
$PPID 父进程的PID
$UID 执行这个脚本的当前用户ID
变量输出
变量内容的输出使用 echo 命令。
如果未使用 echo,则会将变量内容当成 Shell 命令来执行,常用于调用某个程序并传递参数,如:应用程序启动脚本。