数组
在 Bash 脚本中,数组是一种存储多个元素的变量结构,可以使用不同的方式定义和操作数组。
例如,定义数组 arr
并为其分配初始值:
arr=(30 20 10 60) # 数组中的元素值
在这个数组中:
30
为索引0
20
为索引1
10
为索引2
60
为索引3
注意:数组的索引从 0
开始,这和大多数编程语言一致。
数组参数的使用 $* $@ $#
如果在数组中有三个参数 1 2 3
,运行数组脚本后:
"$*"
代表"1 2 3"
(作为一个整体使用)"$@"
代表"1" "2" "3"
(分别作为单个的个体使用)"$#"
表示参数的数量,即3
数组展开示例
定义一个简单的数组:
arr=("a" "b" "c")
使用 *
和 @
进行数组展开的对比:
echo "使用 \\"${arr[*]}\\" 进行展开:"
for item in "${arr[*]}"; do
echo $item
done
echo "使用 \\"${arr[@]}\\" 进行展开:"
for item in ${arr[@]}; do
echo $item
done
数组定义方法
方法一:直接定义
数组名=(value0 value1 value2 …)
示例:
arr=(1 2 3 4 5)
echo ${arr[*]} # 输出:1 2 3 4 5
方法二:指定索引
数组名=([索引]=value [索引]=value …)
示例:
arr=([0]=1 [1]=2 [2]=3)
echo ${arr[*]} # 输出:1 2 3
方法三:引用变量列表
列表名="value0 value1 value2 …"
数组名=($列表名)
示例:
list="1 2 3 4" # 以空格为分隔的列表
arr2=($list)
echo ${arr2[*]} # 输出:1 2 3 4
方法四:逐个赋值
数组名[索引]=value
示例:
arr3[0]="1"
arr3[1]="2"
arr3[2]="3"
echo ${arr3[*]} # 输出:1 2 3
数组包含的数据类型
数组中的数据类型可以是:
- 数值类型
- 字符类型
字符类型需要使用双引号 " "
或单引号 ' '
进行定义。
获取数组长度
使用 ${#数组名[*]}
可以获取数组的长度,即数组中元素的总数。
arr1=(1 2 3 4 5)
echo ${#arr1[*]} # 输出:5
读取特定索引的值
可以通过指定索引来获取数组中的元素值:
arr1=(1 2 3 4 5)
echo ${arr1[0]} # 输出:1
echo ${arr1[3]} # 输出:4
echo ${arr1[*]} # 输出整个数组
索引为空值的情况
若某一索引为空值,使用 ${arr[*]}
查看不到这个空值,会依次查看后面的索引内容,但是读取特定索引(该空值)是可以看到是空值,查看数组长度 ${#arr1[*]}
也可以看到总长度。因此尽可能不放空值。
arr1=("10" "20" " " "30")
echo ${#arr1[*]}
4 # 输出长度
echo ${arr1[*]}
10 20 30 # 输出整个数组
echo ${arr1[2]}
# 输出为空,因为这个索引内容为空值
数组遍历
使用 for
循环遍历数组元素:
arr5=(1 2 3 4 5)
for i in ${arr5[*]} # 或 for i in ${arr5[@]}
do
echo $i
done
数组切片
可以使用切片来获取数组的一部分元素,即以某一位为起始往后取几位:
arr1=(1 2 3 4 5)
echo ${arr1[*]:0:2} # 输出:1 2
echo ${arr1[*]:2:2} # 输出:3 4
数组替换
可以使用替换功能对数组的元素进行临时或永久的替换:
arr1=(1 2 3 4 5)
echo ${arr1[*]/4/66} # 临时替换
# 输出:1 2 3 66 5
arr1=(${arr1[*]/4/66}) # 永久替换
echo ${arr1[*]} # 输出:1 2 3 66 5
删除数组
使用 unset
命令删除整个数组或特定索引的元素:
unset arr1 # 删除整个数组
unset arr1[2] # 删除索引为2的元素
追加数组元素
追加新元素到数组的几种方法:
方法一:直接指定索引
arr1=(1 2 3 4 5)
arr1[5]=6 # 原数组只有5位,追加在第6位
方法二:使用数组长度作为索引
当数组的元素非常多的时候,可以直接使用数组的长度作为将要追加的索引的值。
因为原始数组的索引是从0开始的,所以用长度减去1就是原始数组的最后的以为索引值了,
那么将要添加的值应该是原始索引值的后一位,那显然就等于数组的长度值了。
arr1[${#arr1[*]}]=7
方法三:使用现有数组追加新元素
双引号不能省略,否则,当数组arr1中存在包含空格的元素时会按空格将元素拆分成多个。
不能将@替换为*,如果替换为*,不加双引号时与@的表现一致,加双引号时,会将数组arr1中的所有元素作为一个元素添加到数组中。
简单理解:用*号是作为一个整体,而用@还是单个的个体。
arr1=(1 2 3 4 5)
echo ${arr1[*]}
# 输出:1 2 3 4 5
arr1=("${arr1[@]}" 6 7 8) # 用@可以不加引号,最好不加
echo ${arr1[*]}
# 输出:1 2 3 4 5 6 7 8
# 再如
abc1=(1 2 3 4 5)
echo ${abc1[*]}
# 输出:1 2 3 4 5
abc1=("${abc1[*]}" 6 7 8)
echo ${abc1[*]}
# 输出:1 2 3 4 5 6 7 8
拓展:遍历元素输出
for i in ${arr1[*]}
> do
> echo $i
> done
1
2
3
4
5
6
7
8
# 再如
for i in "${abc1[@]}";do echo $i;done
1 2 3 4 5
方法四:使用 +=
操作符
待添加元素必须用“()"包围起来,并且多个元素用空格分隔。
arr1=(1 2 3 4 5)
echo ${arr1[*]}
# 输出:1 2 3 4 5
arr1+=(11 22) # 此处追加
echo ${arr1[*]}
# 输出:1 2 3 4 5 11 22
插入数组元素
在数组 arr
的指定位置插入一个新元素,在 arr[4]
的位置插入数字 5
。
方法一:直接插入
#!/bin/bash
# 定义初始数组
arr=(1 2 3 4 6 7)
# 在 arr[4] 位置插入数字 5
arr=("${arr[@]:0:4}" 5 "${arr[@]:4}")
# 输出结果
echo "插入后的数组为:${arr[*]}"
# 输出:插入后的数组为:1 2 3 4 5 6 7
方法二:使用for循环
依次循环赋值元素到新数组,遇到待插入的元素先赋值新元素
#!/bin/bash
# 定义初始数组
arr=(1 2 3 4 6 7)
# 新数组
new_arr=()
# 指定插入位置
insert_position=4
# 要插入的值
insert_value=5
# 使用for循环遍历原数组并插入新值
for ((i = 0; i < ${#arr[@]}; i++)); do
# 如果当前索引是插入位置
if [ $i -eq $insert_position ]; then
new_arr+=("$insert_value") # 插入新值
fi
# 插入原数组的元素
new_arr+=("${arr[i]}")
done
# 如果插入位置超出了数组的末尾,将新值添加到最后
if [ $insert_position -ge ${#arr[@]} ]; then
new_arr+=("$insert_value")
fi
# 输出结果
echo "插入后的数组为:${new_arr[*]}"
# 输出:插入后的数组为:1 2 3 4 5 6 7
方法三:使用换位的逻辑
后移腾出新位置,新元素直接插入到新位置
#!/bin/bash
# 定义初始数组
arr=(1 2 3 4 6 7)
# 指定插入位置
insert_position=4
# 要插入的值
insert_value=5
# 扩展数组大小,将最后一个元素再添加一次
arr+=("${arr[-1]}")
# 使用for循环从后往前移动元素,为插入的新元素腾出位置
for ((i=${#arr[@]}-2; i>=insert_position; i--)); do
arr[$((i + 1))]=${arr[$i]}
done
# 在指定位置插入新元素
arr[$insert_position]=$insert_value
# 输出结果
echo "插入后的数组为:${arr[*]}"
# 输出:插入后的数组为:1 2 3 4 5 6 7
向函数传递数组参数
- (缺陷)直接传递整个数组变量
如果将数组变量作为函数参数,函数只会取数组变量的第一个值。
#!/bin/bash
test1 () {
echo "接收到的参数列表:$@"
abc2=$1
echo "新数组的值为:${abc2[*]}"
}
abc=(3 2 1 4 5)
test1 $abc
#将数组变量作为函数的参数,只会取数组变量的第一个值
执行结果:
[root@loaclhost shuzu1]#chmod +x b.sh
[root@loaclhost shuzu1]#./b.sh
原始数组的值为:3 2 1 4 5
接受到的参数列表:3
新数组的值为:3
- (解决方法)将数组元素拆分为单个参数
将数组变量的值分解成单个的值,然后将这些值作为函数参数使用。在函数内部,再将所有的参数重新组合成一个新的数组变量。
#!/bin/bash
test2 () {
abc1=($(echo $@)) # 或者表示为 abc1=(`echo $@`)
echo "新数组的值为:${abc1[*]}"
}
abc=(`seq 1 10`)
test2 ${abc[*]} # 将数组的值分解为单个的值
执行结果:
[root@loaclhost shuzu1]#chmod +x c.sh
[root@loaclhost shuzu1]#./c.sh
新数组的值为:1 2 3 4 5 6 7 8 9 10
-
从函数返回数组:数组元素运算
示例1:加法传参运算
#!/bin/bash test2 () { abc1=(`echo $@`) sum=0 for i in ${abc1[*]} do sum=$((sum + i)) # 或sum=$[$sum + $i] done echo "$sum" } abc=(3 2 1 4 5) test2 ${abc[*]} # 输出数组元素的和
执行结果:
[root@localhost shuzu1]# ./c.sh 15
示例2:乘法传参运算
#!/bin/bash test3 () { abc1=(`echo $@`) #for ((i=0; i<$#; i++)) # $#为参数的个数 for ((i=0; i<=$[$# - 1]; i++)) # $#是原始数组的元素个数,这里取出新数组的索引值,不减的话就是一个字符串 do abc1[$i]=$((abc1[$i] * 2)) # 每个元素乘以2 # 将每个原始索引对应的元素值乘以2传到新的数组中对应的索引的元素中去 done echo "${abc1[*]}" # 输出新数组 } abc=(1 2 3) test3 ${abc[*]}
执行结果:
[root@localhost shuzu1]# ./c.sh 2 4 6