Linux shell的数组详解
- 前提
- 变量
- 数组
- 数组声明
- 声明索引数组
- 声明关联数组
- 数组赋值
- 数组引用
- 数组中常用的变量
- 数组中的其它操作
- 示例
前提
程序是指 指令 + 数据 的组合。
- 指令:bash脚本中的代码(函数、调用的命令等)
- 数据:变量、数组、文件等
变量
变量 是 存储单个元素的内存空间。
数组
数组 是 存储多个元素的连续的内存空间。
数组格式:
# 数组名[数组索引]
# 数组名:整个数组只有一个名字;
# 数组索引:编号从0开始;0 1 2 3 4 5
数组引用:
# ${ARRAY_NAME[INDEX]}
# 注意:一定要带花括号,如果不带花括号的话,默认只会引用数组的第一个元素,如下:
# $ARRAY_NAMR[INDEX] 只会引用数组的第一个数
示例:
[root@LeeMumu ~]# Lover[0]=JiaoTang
[root@LeeMumu ~]# Lover[1]=NEO
[root@LeeMumu ~]# Lover[2]=Pangpang
[root@LeeMumu ~]# echo ${Lover[0]}
JiaoTang
[root@LeeMumu ~]# echo ${Lover[1]}
NEO
[root@LeeMumu ~]# echo $Lover[1]
JiaoTang[1]
[root@LeeMumu ~]# echo $Lover
JiaoTang
数组声明
声明数组时可以声明索引数组或者关联数组,但是只有bash-4及以后的版本,支持自定义索引格式,而不仅仅是 0,1,2, …数字格式。
# declare -a NAME # 声明索引数组
# declare -A NAME # 声明关联数组
查看bash版本:
[root@LeeMumu ~]# rpm -q bash
bash-4.2.46-31.el7.x86_64
声明索引数组
[root@LeeMumu ~]# Lover[0]=JiaoTang
[root@LeeMumu ~]# Lover[1]=NEO
[root@LeeMumu ~]# Lover[2]=Pangpang
[root@LeeMumu ~]# echo ${Lover[0]}
JiaoTang
[root@LeeMumu ~]# echo ${Lover[1]}
NEO
声明关联数组
**注意:**关联数组一定要事先声明才行,不然会按照索引数组进行执行。如下两个示例。
[root@LeeMumu ~]# declare -A LOVER
[root@LeeMumu ~]# LOVER[NEO]=NEO
[root@LeeMumu ~]# LOVER[JiaoTang]=JiaoTang
[root@LeeMumu ~]# echo LOVER[NEO]
LOVER[NEO]
[root@LeeMumu ~]# echo ${LOVER[NEO]}
NEO
[root@LeeMumu ~]# echo ${LOVER[JiaoTang]}
JiaoTang
[root@LeeMumu ~]# Lover[JL]=NEO
[root@LeeMumu ~]# Lover[JC]=JiaoTang
[root@LeeMumu ~]# echo ${Lover[JL]}
JiaoTang
[root@LeeMumu ~]# echo ${Lover[JC]}
JiaoTang
数组赋值
数组中元素的赋值方式主要有几个方式:
- 一次只能赋值一个元素
# ARRAY_NAME[INDEX]=value
- 一次赋值全部元素
# ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)
- 只赋值特定元素
# ARRAY_NAME=([0]="VAL1" [3]="VAL4" ...)
- 交互式赋值
# read -a ARRAY_NAME
备注:bash支持稀疏格式的数组
数组引用
引用数组中的元素:${ARRAY_NAME[INDEX]}
# 注意:引用时,只给数组名,表示引用下标为0的元素
数组中常用的变量
数组中常用的变量如下:
${#ARRAY_NAME[*]} # 数组中元素的个数
${#ARRAY_NAME[@]} # 数组中元素的个数
${ARRAY_NAME[*]} # 引用数组中的所有元素
${ARRAY_NAME[@]} # 引用数组中的所有元素
${#ARRAY_NAME} # 数组中下标为 0 的字符个数
数组切片引用:
命令格式:
${ARRAY_NAME[@]:offset:number}
# offset:要路过的元素个数
# number:要取出的元素个数;省略number时,表示取偏移量之后的所有元素
示例1:
[root@LeeMumu ~]# echo ${#Lover[*]}
3
[root@LeeMumu ~]# echo ${#Lover[@]}
3
[root@LeeMumu ~]# echo ${Lover[*]}
JiaoTang NEO Pangpang
[root@LeeMumu ~]# echo ${#Lover}
8
[root@LeeMumu ~]# echo ${Lover[0]}
JiaoTang
示例2:
# 把/etc/目录下以p或者P开头的文件名赋值到files数组中
[root@LeeMumu ~]# ls -d /etc/[pP]*
/etc/pam.d /etc/passwd- /etc/pki /etc/pm /etc/popt.d /etc/ppp /etc/printcap /etc/profile.d /etc/python
/etc/passwd /etc/pkcs11 /etc/plymouth /etc/polkit-1 /etc/postfix /etc/prelink.conf.d /etc/profile /etc/protocols
[root@LeeMumu ~]# files=(/etc/[Pp]*)
[root@LeeMumu ~]# echo ${files[*]}
/etc/pam.d /etc/passwd /etc/passwd- /etc/pkcs11 /etc/pki /etc/plymouth /etc/pm /etc/polkit-1 /etc/popt.d /etc/postfix /etc/ppp /etc/prelink.conf.d /etc/printcap /etc/profile /etc/profile.d /etc/protocols /etc/python
[root@LeeMumu ~]# echo ${files[@]:2:3}
/etc/passwd- /etc/pkcs11 /etc/pki
[root@LeeMumu ~]# echo ${files[@]:5}
/etc/plymouth /etc/pm /etc/polkit-1 /etc/popt.d /etc/postfix /etc/ppp /etc/prelink.conf.d /etc/printcap /etc/profile /etc/profile.d /etc/protocols /etc/python
[root@LeeMumu ~]# echo ${#files[*]}
17
[root@LeeMumu ~]# echo ${#files[@]}
17
数组中的其它操作
# 向非稀疏格式数组中追加元素
ARRAY_NAME[${#ARRAY_NAME[*]}]=
# 删除数组中的某元素
unset ARRAY[INDEX]
# 关联数组
declare -A ARRAY_NAME
# 关联数组赋值
ARRAY_NAME=([index_name1]="value1" [index_name2]="value2" ...)
示例
- 生成10个随机数,并找出其中的最大值和最小值。
[root@LeeMumu ~]# bash sort10.sh
28039
15431
2321
28443
4768
19176
30361
18180
935
1574
The max of the ten random integers is : 30361 .
The min of the ten random integers is : 935 .
[root@LeeMumu ~]# cat sort10.sh
#!/bin/bash
#
declare -a rand
declare -i max=0
declare -i min=0
for i in {0..9}; do
rand[$i]=$RANDOM
echo ${rand[$i]}
[ ${rand[$i]} -gt $max ] && max=${rand[$i]}
done
for j in {1..8}; do
[ ${rand[$j]} -lt ${rand[$j-1]} ] && min=${rand[$j]}
done
echo "The max of the ten random integers is : $max ."
echo "The min of the ten random integers is : $min ."
- 定义一个数组,数组中的元素是/var/log目录下所有以.log结尾的文件;统计其下标为偶数的文件中的行数之和。
[root@LeeMumu ~]# bash fileseven.sh
The even file /var/log/boot.log has 157 Lines .
The even file /var/log/vmware-network.2.log has 21 Lines .
The even file /var/log/vmware-network.4.log has 146 Lines .
The even file /var/log/vmware-network.6.log has 16 Lines .
The even file /var/log/vmware-network.8.log has 16 Lines .
The even file /var/log/vmware-network.log has 16 Lines .
The even file /var/log/yum.log has 114 Lines .
The even files have toutally 486 Lines .
[root@LeeMumu ~]# cat fileseven.sh
#!/bin/bash
#
declare -a files
files=(/var/log/*.log) # 后续()会进行命令行展开,生成文件名称序列
declare -i lines=0
for i in $(seq 0 $[${#files[*]}-1]); do
if [ $[$i%2] -eq 0 ]; then
echo "The even file ${files[$i]} has $(wc -l ${files[$i]} | cut -d' ' -f1) Lines ."
let lines+=$(wc -l ${files[$i]} | cut -d' ' -f1)
fi
done
echo "The even files have toutally $lines Lines ."