
正文
Bash脚本编程之数组
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
数组简介
在bash脚本编程当中,变量是存储单个元素的内存空间;而数组是存储多个元素的一段连续的内存空间。
数组由数组名和下标构成,如下。
ARRAY_NAME[SUBSCRIPT]
数组按照下标的类型可分为两种:
- 索引(indexed)数组:下标为0、1、2等非负整数。
- 关联(associative)数组:下标为用户自定义的字符串。
数组的操作声明
索引数组可以不声明直接使用;而关联数组如果不声明直接使用的话,会被认为是索引数组,即使它的下标是字符串。
索引数组的声明方式。
# declare -a ARRAY_NAME
关联数组的声明方式。
# declare -A ARRAY_NAME
赋值
一次只赋值一个元素。
# ARRAY_NAME[SUBSCRIPT]=VALUE
一次赋值全部元素。
# ARRAY_NAME = ("VAL1" "VAL2" "VAL3" ...)
一次赋值多个可以是不连续的元素。
# ARRAY_NAME = ([] = "VAL1" [] = "VAL3")
像这种不要求元素必须依次存在的数组(即可以在没有A[1]和A[2]的时候就赋值A[3]),叫做稀疏格式数组。因此,bash支持稀疏格式的数组。
读取标准输入赋值数组。
# read -a ARRAY_NAME
在输入的时候,以空格作为元素的分隔符,以回车键结束元素的赋值。
向数组的末尾追加元素。
ARRAY_NAME[${#ARRAY_NAME[@]}]=VALUE
或者
ARRAY_NAME+=(VALUE)
引用
引用单个数组元素。
${ARRAY_NAME[SUBSCRIPT]}
如果省略SUBSCRIPT,那么就等同于SUBSCRIPT=0。即以下两个引用是相同的。
${ARRAY_NAME[]}
${ARRAY_NAME}
下标可以是一个变量,当下标是一个变量的时候,可以省略掉展开下标变量字符“$”。即${array[$var]}=${array[var]}。
[root@c7-server ~]# declare -a name=(bu jing yun)
[root@c7-server ~]# echo ${name[*]}
bu jing yun
[root@c7-server ~]# declare -i a= b= c=
[root@c7-server ~]# echo ${name[$a]}
bu
[root@c7-server ~]# echo ${name[$b]}
jing
[root@c7-server ~]# echo ${name[$c]}
yun
[root@c7-server ~]# echo ${name[a]}
bu
[root@c7-server ~]# echo ${name[b]}
jing
[root@c7-server ~]# echo ${name[c]}
yun
引用数组的所有元素。正常情况下,二者没有区别,只有当被双引号包裹的时候,“@”被展开为每个元素为一个独立的单词;“*”被展开为所有元素为一个统一的单词。
${ARRAY_NAME[@]}
${ARRAY_NAME[*]}
引用数组元素的长度。
${#ARRAY_NAME[SUBSCRIPT]}
引用数组的长度,即数组的元素个数。
${#ARRAY_NAME[@]}
${#ARRAY_NAME[*]}
引用数组的部分元素(切片)。
${ARRAY_NAME[@]:OFFSET:NUMBER}
${ARRAY_NAME[*]:OFFSET:NUMBER}
OFFSET:偏移,表示偏移/跳过数组中的前几个元素。
NUMBER:表示偏移后取几个元素。
如果省略了NUMBER,并且OFFSET的值为“ -n”(注意,-n的左边有空格),则表示引用倒数的n个元素。
截止目前我们引用的都是数组的值,如果我们想引用数组的下标的话,可以使用:
${!ARRAY_NAME[@]}
${!ARRAY_NAME[*]}
删除
删除数组元素。
# unset ARRAY_NAME[SUBSCRIPT]
删除数组。
# unset ARRAY_NAME
数组示例
定义一个索引数组,逐一赋值数组元素。
[root@c7-server ~]# declare -a my_array
[root@c7-server ~]# my_array[]=zhang
[root@c7-server ~]# my_array[]=wen
[root@c7-server ~]# my_array[]=long
根据数组下标获取数组元素。留意我们上文说的,当引用数组不带下标的时候,等同于引用${ARRAY_NAME[0]}。
[root@c7-server ~]# echo ${my_array}
zhang
[root@c7-server ~]# echo ${my_array[]}
zhang
[root@c7-server ~]# echo ${my_array[]}
wen
[root@c7-server ~]# echo ${my_array[]}
long
引用数组中的所有元素,顺便测试一下“@”和“*”的区别。注意,这个区别,仅在${my_array[@]}或者${my_array[*]}被双引号包裹的情况下才会出现。
[root@c7-server ~]# echo ${my_array[@]}
zhang wen long
[root@c7-server ~]# echo ${my_array[*]}
zhang wen long
[root@c7-server ~]# for i in "${my_array[@]}"; do echo $i; done
zhang
wen
long
[root@c7-server ~]# for i in "${my_array[*]}"; do echo $i; done
zhang wen long
引用数组个数。
[root@c7-server ~]# echo ${#my_array[@]}[root@c7-server ~]# echo ${#my_array[*]}
引用数组中元素的个数。
[root@c7-server ~]# echo ${my_array[]}
zhang
[root@c7-server ~]# echo ${#my_array[]}
接下来演示其他几种不同的赋值方式,操作前可先删除数组。
[root@c7-server ~]# unset my_array
[root@c7-server ~]# my_array=([]=zhang []=wen []=long)
[root@c7-server ~]# echo ${my_array[@]}
zhang wen long
[root@c7-server ~]# unset my_array
[root@c7-server ~]# read -a my_array
Mon Tue Wed Thu Fri Sat Sun
[root@c7-server ~]# echo ${my_array[@]}
Mon Tue Wed Thu Fri Sat Sun
数组元素去子串(substring),即切片。
[root@c7-server ~]# echo ${my_array[@]}
Mon Tue Wed Thu Fri Sat Sun
[root@c7-server ~]# echo ${my_array[@]::}
Thu Fri
[root@c7-server ~]# echo ${my_array[@]::}
Wed Thu Fri
[root@c7-server ~]# echo ${my_array[@]: -}
Fri Sat Sun
数组元素追加。
[root@c7-server ~]# echo ${my_array[@]}
Mon Tue Wed Thu Fri Sat Sun
[root@c7-server ~]# my_array+=(ddd)
[root@c7-server ~]# my_array[${#my_array[@]}]=eee
[root@c7-server ~]# echo ${my_array[@]}
Mon Tue Wed Thu Fri Sat Sun ddd eee
引用数组的下标(subscript)。个人感觉引用数组下标在关联数组中比较有用,在索引数组中用处不大。
[root@c7-server ~]# echo ${!my_array[@]}[root@c7-server ~]# unset my_array
[root@c7-server ~]# declare -A my_array
[root@c7-server ~]# my_array=([name]=zwl [age]= [sex]=male)
[root@c7-server ~]# echo ${my_array[@]}
zwl male
[root@c7-server ~]# echo ${!my_array[@]}
name age sex
练习题题一:生成10个100以内的非负整数并存入数组当中,对其进行排序然后输出最大值和最小值。
这道题,涉及到算法中的冒泡排序,可以参考一下《冒泡排序_百度百科》中的概念解释,以及《1.1 冒泡排序 | 菜鸟教程》中的图示,这个GIF图真的超棒!
按照升序排序后,最大值和最小值取头尾即可。
代码示例。
#!/bin/bashdeclare -a rand
declare -i rand_length var
for i in {..}; do
rand[$i]=$((RANDOM%))
done
echo -e "The original array is \t${rand[*]}."
rand_length=${#rand[*]}
#echo $rand_lengthfor i in $(seq $((rand_length-)) | sort -nr); do
for((j=;j<$i;j++)); do
if [ ${rand[j]} -gt ${rand[((j+))]} ]; then
var=${rand[j]}
rand[j]=${rand[j+]}
rand[j+]=$var
fi
done
#echo ${rand[*]}
doneecho -e "The last array is \t${rand[*]}."
echo "The min of the array is ${rand[0]}."
echo "The max of the array is ${rand[-1]}."
结果演示。
[root@c7-server ~]# bash arrayBubbleSort.sh
The original array is .
The last array is .
The min of the array is .
The max of the array is .
[root@c7-server ~]# bash arrayBubbleSort.sh
The original array is .
The last array is .
The min of the array is .
The max of the array is .
[root@c7-server ~]# bash arrayBubbleSort.sh
The original array is .
The last array is .
The min of the array is .
The max of the array is .
看懂代码以后,我们可以调整一下echo语句,就可以看到每次循环排序的结果。
The original array is .10 21 34 36 50 52 57 68 83 98
从结果中我们也会发现,除非是刚好是倒序的情况,否则在循环的中途就可以排序完成了。
这个脚本,个人觉得还是会稍微难点的,尤其是对于算法基础薄弱且非编程的人员,我也是Google后才知道结果的,真的搞不懂的同学,不必纠结,将来再补算法即可,这篇随笔主要是了解数组的。
题二:定义一个数组,数组元素为/var/log/目录下所有以.log结尾的文件的文件名;统计下标为偶数的文件的行数并求和。
#!/bin/bashdeclare -a filePool=(/var/log/*.log)
declare -i sum=0
declare -i linefor i in $(seq 0 $((${#filePool[*]}-1))); do
if [ $((i%2)) -eq 0 ]; then
line=$(wc -l ${filePool[i]} | cut -d " " -f 1)
((sum+=line))
fi
doneecho "The sum of lines which meet the conditions is $sum."







