shell 数组的使用

数组的定义

在 Shell 中,数组的定义非常简单。以下是几种常见的定义方式:

1、普通定义

1
2
3
4
5
num=(1 2 3 4 5)
str=('a' 'b' 'c' 'd' 'e')
# 也可直接定义下标值
str[0]='a'

2、特殊定义

1
2
3
4
5
6
7
8
9
10
# for循环中声明
for i in {1..5}; do
echo $i

# 自定义分隔符
str="a,b,c,d,e"
IFS=","
arr=($str)
这时候arr数组中的值就是str中的“a b c d e”,需要注意的是,分隔符 (IFS) 被重新定义后,可能会影响其他代码,所以最好在使用后还原 IFS

3、关联数组
这个需要在bash 4版本以上才能用。关联数组允许你使用字符串作为数组的索引。

1
2
3
# 预先定义一个数组,包含一些指定的字符串
declare -a my_array=("Apple" "Banana" "Cherry" "Date" "Elderberry" "Fig" "Grape")

这样做的优点是可以用来做参数的传递,举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
get_random_str() {
local array_name=$1
local -n array=$2


if [ ${#array[@]} -eq 0 ]; then
echo "Array is empty."
return 1
fi

local random_index=$((RANDOM % ${#array[@]}))

STR="${array[random_index]}"
}

get_random_str "my_array" my_array

4、直接初始化

1
2
3
4
5
6
7
8
9
10
# 初始化一个空数组
arr=()

# 从命令输出初始化
arr=($(ls)) # 将当前目录下的文件名作为数组元素

# 使用扩展初始化
num=({1..10}) # 生成一个包含从1到10的数字数组
letters=({a..z}) # 生成一个包含a到z的字母数组

示例

1、数组的遍历

  • 方法一:通过索引遍历
1
2
3
4
5
6
7
# ${#num[@]} # 获取数组的长度

for((i=0;i<${#num[@]};i++))
do
echo "num is: ${num[i]}"
done

  • 方法二:直接遍历数组元素
    1
    2
    3
    4
    5
    # ${num[*]} 或者 ${num[@]}
    for nu in ${num[*]}
    do
    echo "num is: $nu"
    done
  • 其他:获取关联数组所有的下标值的数组
    1
    2
    3
    4
    5
    for key in "${!my_array[@]}"; do
    echo "key is: $key"
    echo "value is: ${my_array[$key]}"
    done

2、数组的添加

1
2
3
4
5
6
7
8
9
# 把数组中的值添加到数组的开头
num=(x ${num[@]})

# 把数组中的值添加到数组的末尾
num=(${num[@]} x)

# 把其他数组中的值添加到数组的末尾
num=(${num[@]} ${num2[@]})

3、数组的删除

1
2
3
4
5
# 删除数组中的某个值
unset num[1] # 删除 num 数组中的第二个元素
unset my_array[Apple] # 删除 my_array 中键为 Apple 的元素
# 删除整个数组
unset num

4、数组切片(子数组)

1
2
sub_array=("${arr[@]:2:3}")  # 从索引2开始,提取3个元素

5、关联数组的高级操作

关联数组允许使用字符串作为键:

1
2
3
4
5
6
7
8
9
# 检查键是否存在
if [[ -v my_array[Apple] ]]; then
echo "Apple exists in my_array"
fi

# 关联数组的键值对遍历
for key in "${!my_array[@]}"; do
echo "$key => ${my_array[$key]}"
done

6、参数传递

1
2
3
4
5
6
7
8
print_array() {
local -n arr_ref=$1
for element in "${arr_ref[@]}"; do
echo "$element"
done
}

print_array arr # 传递数组的引用

优化与注意事项

1、IFS 的使用:在使用完自定义的 IFS 后,建议立即还原,以免影响脚本中其他部分的分隔符处理。

1
2
3
4
5
复制代码
OLD_IFS=$IFS
IFS=","
arr=($str)
IFS=$OLD_IFS

2、使用 declare 定义数组:在定义关联数组时,推荐使用 declare -A 来显式声明数组类型,这有助于避免错误并增强代码可读性。

3、RANDOM 的使用:当使用 RANDOM 来生成随机数时,注意随机数种子问题,在需要固定输出的场景中可以预先设置种子。