数组和关联数组(associative array)的初始化语法类似。
# 定义数组
declare -a array=(alpha beta omega)
# 定义关联数组
declare -A dict=(
[key1]=alpha
[key2]=beta
[key3]=omega
[key4]=''
)
取 length、Key、Value 的操作都一样,数组和关联数组没有区别。
echo "# 取长度"
echo ${#dict[*]}
echo ${#dict[@]}
echo "# 取所有 Key"
echo ${!dict[*]}
echo ${!dict[@]}
echo "# 取所有 Value"
echo ${dict[*]}
echo ${dict[@]}
判断数组是否包含一个元素,最简便的方法是通过数组的 Substring Replacement
,请参考
echo '# 检查数组是否包含一个元素'
[[ "${array[@]/omega/}" != "${array[@]}" ]] && echo "in" || echo "not in"
[[ "${array[@]/gamma/}" != "${array[@]}" ]] && echo "in" || echo "not in"
检查一个关联数组是否包含某个 Key,和检查一个变量是否设置的方法类似,使用 Parameter Expansion
的 ${parameter+word}
,参考 Test if element is in array in bash,
${parameter+word} 的用法请参考 Use an alternate value,基本上Bash 的 Parameter Expansion 都是判断变量是否设置,已经设置了值是否为空。
echo "# 检查关联数组 key 是否存在(允许 Value 为空)"
if [[ -n "${dict[${key_name}]+X}" ]]; then
printf '%s\n' "$key_name is in Array."
else
printf '%s\n' "$key_name isn't in Array."
fi
遍历数组也都一样。其实数组也是有 Key 的,直接用下面遍历关联数组的命令,遍历一下普通数组就能看到从 0 开始的索引。
echo "# 遍历数组"
for i in ${array[@]}; do
echo $i
done
echo "# 遍历关联数组"
for key in ${!dict[@]}; do
printf "%-5s: %-6s\n" $key ${dict[${key}]};
done
数组的间接引用和使用数组作为行参
declare -a g_ary=( 1 2 3 )
a () {
declare -a ary=${!1}
ary+=(4)
echo ${ary[@]}
unset ary
}
a g_ary[@]
echo ${g_ary[@]}
遍历数组的其它特殊情况
$ » for i in "${a1[@]}"; do echo "${i}." ; done
a.
.
.
null.
$ » for i in ${a1[@]}; do echo "${i}". ; done
a.
null.
$ » declare -a a2
$ » for (( i=0; i <= ${#a2[@]}; i=i+1 )) ; do echo "${i} : ${a2[${i}]}."; done
-bash: a2[${i}]: unbound variable
$ » for i in "${a2[@]}"; do echo "${i}." ; done
-bash: a2[@]: unbound variable
Bash 的 nounset 属性和空数组
#!/bin/bash
#
set -o nounset
declare -a ary=( $(find /tmp/ -depth -mindepth 1 -maxdepth 1 -type d -mtime +1 -printf "%P ") ) # (1)
for (( i = 0 ; i < ${#ary[@]} ; i=i+1 )) # (2)
do
if [[ -n ${ary[${i}]} ]]
then
echo ${ary[${i}]}
fi
done
for i in ${ary[@]} # (3)
do
if [[ -n ${i} ]]
then
echo ${i}
fi
done
declare -a a1=( 'a' ' ' '' 'null' ) # (4)
for (( i=0; i <= ${#a1[@]}; i=i+1 ))
do
if [[ -n ${a1[${i}]} ]]
then
echo "${i} : ${a2[${i}]}."
fi
done
-
如果
find
命令没有输出,则数组ary
的值为空。 -
这里的
for
循环取长度的操作可能是因为只取长度,不需要展开数组求值,再加循环体里面的if
语句,也不会对数组元素求职,这种写法不受 nounset 影响。 -
因为开启了
nounset
属性, 这里的for
循环会在结束之后提示unbound variable
退出脚本。 -
如果数组元素的值是空格(
' '
)是不受 nounset 限制的,但是元素的值为空字符串(''
),还是会报unbound variable
,脚本在执行完for
循环之后中止退出;由于空格还是会执行for
循环,最好还是给变量加上双引号。
更多用法请参考 ABS Chapter 27. Arrays。
解释的很细致,感谢!