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

数组赋值

数组中元素的赋值方式主要有几个方式:

  1. 一次只能赋值一个元素
# ARRAY_NAME[INDEX]=value
  1. 一次赋值全部元素
# ARRAY_NAME=("VAL1"  "VAL2"  "VAL3"  ...)
  1. 只赋值特定元素
# ARRAY_NAME=([0]="VAL1"  [3]="VAL4" ...)
  1. 交互式赋值
# 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" ...)

示例

  1. 生成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 ."
  1. 定义一个数组,数组中的元素是/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 ."