返回顶部

zhangfd

个人博客,仅供学习使用

导航

shell编程 13 --- shell 数组的应用实践

shell编程 13 --- shell 数组的应用实践

13.1 shell数组介绍


数组的概念:

简单地说, Shell的数组就是一个元素集合,它把有限个元素(变量或字符内容)用一个名字来命名,然后用编号对它们进行区分。这个名字就称为数组名,用于区分不同内容的编号就称为数组下标。组成数组的各个元素(变量)称为数组的元素,有时也称为下标变量。

有了Shell数组之后,就可以用相同名字来引用一系列变量及变量值了,并通过数字(索引)来识别使用它们。在很多场合中,使用数组可以缩短和简化程序开发。


13.2 shell数组的定义与增删改查

13.2.1 shell数组的定义

Shell数组的定义有多种方法,列举如下。

方法1:用小括号将变量值括起来赋值给数组变量,每个变量值之间要用空格进行分隔。语法如下:

推荐使用

array=(value1 value2 value3 value4 ...)
## 实例:
[root@zabbix 0514]# array=(1 2 3)
[root@zabbix 0514]# echo ${array[*]} 
1 2 3

方法2:用小括号将变量值括起来,同时采用键值对的形式赋值。语法如下:

此方法比较复杂,不推荐使用

[root@zabbix 0514]# array=([1]=one [2]=two [3]=three)
[root@zabbix 0514]# echo ${array[*]}
one two three
[root@zabbix 0514]# echo ${array[1]}
one
[root@zabbix 0514]# echo ${array[2]}
two
[root@zabbix 0514]# echo ${array[3]}
three

方法3:通过分别定义数组变量的方法来定义。语法如下:

此方法比较复杂,不推荐使用

[root@zabbix 0514]# array[0]=a;array[1]=b;array[2]=c;
[root@zabbix 0514]# echo ${array[*]}
a b c

方法4:动态地定义数组变量,并使用命令的输出结果作为数组的内容。语法为:

array=($(命令)) 或 array=(`命令`)

实例:

[root@zabbix 0514]# mkdir array
[root@zabbix 0514]# touch array/{1..3}.txt
[root@zabbix 0514]# ll array/
total 0
-rw-r--r-- 1 root root 0 May 14 10:06 1.txt
-rw-r--r-- 1 root root 0 May 14 10:06 2.txt
-rw-r--r-- 1 root root 0 May 14 10:06 3.txt
[root@zabbix 0514]# array=($(ls array/))
[root@zabbix 0514]# echo ${array[*]}
1.txt 2.txt 3.txt

13.2.2 Shell数组的打印和输出

13.2.2.1.打印数组元素
[root@zabbix 0514]# array=(one two three four) 		== 定义数组
[root@zabbix 0514]# echo ${array[1]}				== 打印单个元素
two
[root@zabbix 0514]# echo ${array[0]}				== 数组下标从0开始
one
[root@zabbix 0514]# echo ${array[*]}	
one two three four
[root@zabbix 0514]# echo ${array[@]}				== 使用*和@可以得到整个数组元素
one two three four
[root@zabbix 0514]#
13.2.2.2.打印数组元素的个数
# 用${#数组名[*]} 或 ${#数组名[@]} 可以得到数组长度
[root@zabbix 0514]# echo ${array[*]}
one two three four
[root@zabbix 0514]# echo ${#array[*]}
4
[root@zabbix 0514]# echo ${array[@]}
one two three four
[root@zabbix 0514]# echo ${#array[@]}
4
13.2.2.3.数组赋值

可直接通过“数组名[下标]”对数组进行引用赋值,如果下标不存在,则自动添加一个新的数组元素,
如果下标存在,则覆盖原来的值。

[root@zabbix 0514]# array=(one two three four)
[root@zabbix 0514]# echo ${array[@]}
one two three four
[root@zabbix 0514]# echo ${array[0]}
one
[root@zabbix 0514]# array[0]=moox		==> 修改数组元素,覆盖先前元素
[root@zabbix 0514]# echo ${array[0]}	
moox
[root@zabbix 0514]# echo ${array[@]}
moox two three four
[root@zabbix 0514]# echo ${array[4]}

[root@zabbix 0514]# array[4]=new		==> 赋值新元素
[root@zabbix 0514]# echo ${array[4]}
new
13.2.2.4.数组的删除

因为数组本质上还是变量,因此可通过“unset数组[下标]”清除相应的数组元素,
如果不带下标,则表示清除整个数组的所有数据。

[root@zabbix 0514]# echo ${array[*]}
moox two three four new
[root@zabbix 0514]# unset array[1]
[root@zabbix 0514]# echo ${array[*]}
moox three four new
[root@zabbix 0514]# unset array
[root@zabbix 0514]# echo ${array[*]}

[root@zabbix 0514]# 
13.2.2.5.数组内容的截取、替换和删除

这里和前文变量子串的替换是一样的,因为数组是特殊的变量。
数组元素部分的内容截取的示例如下:

[root@zabbix 0514]# array=(1 2 3 4 5)
[root@zabbix 0514]# echo ${array[@]:1:3}
2 3 4
[root@zabbix 0514]# array=($(echo {a..z}))
[root@zabbix 0514]# echo ${array[@]}
a b c d e f g h i j k l m n o p q r s t u v w x y z
[root@zabbix 0514]# echo ${array[@]:4:5}
e f g h i
=========================================================
说明:echo ${array[@]:4:5}截取时,4表示数组下标开始的位置,5表示截取的长度,如:
[root@zabbix 0514]# echo ${array[@]:4:1}
e

替换数组元素部分内容的代码如下:

[root@zabbix 0514]# array=(1 2 3 1 1)
[root@zabbix 0514]# echo ${array[*]}
1 2 3 1 1
[root@zabbix 0514]# echo ${array[*]/1/b}
b 2 3 b b
========================================================
提示:调用方法为${数组名[@或*]/查找字符/替换字符},该操作不会改变原先数组的内容,
如果需要修改,可以参考上面的例子,重新定义数组。

删除数组元素部分内容的代码如下:

[root@zabbix 0514]# array=(one one1 two two1 three three1  four four1 left)
[root@zabbix 0514]# echo ${array[*]#f*}			==> 删除数组中以f开头的元素中的f
one one1 two two1 three three1 our our1 left
[root@zabbix 0514]# echo ${array[*]##f*}		==> 删除数组中以f开头的元素
one one1 two two1 three three1 left
=======================================================================
[root@zabbix 0514]# echo ${array[*]}
one one1 two two1 three three1 four four1 left
[root@zabbix 0514]# echo ${array[*]%1*}			==> 删除数组中以1结尾的元素中的1
one one two two three three four four left

13.3 shell 数组脚本开发实践

13.3.1 使用循环批量输出数组的元素

范例13-1:使用循环批量输出数组的元素。

方法1:通过C语言型的for循环语句打印数组元素。

[root@zabbix 0514]# cat for_c.sh 
#!/bin/bash
array=(1 2 3 4 5)
for((i=0;i<${#array[*]};i++))
do
    echo ${array[i]}
done
[root@zabbix 0514]# sh for_c.sh 
1
2
3
4
5

方法2:通过普通for循环语句打印数组元素。

[root@zabbix 0514]# cat array_1.sh 
#!/bin/bash
array=(1 2 3 4 5)
for n in ${array[*]}
do
    echo $n
done

方法3:使用while循环语句打印数组元素。

[root@zabbix 0514]# cat array_while.sh 
#!/bin/bash
array=(1 2 3 4 5)
i=0
while ((i<${#array[*]}))
do
    echo ${array[i]}
    ((i++))
done

13.3.2 竖向列举法定义数组元素并批量打印

范例13-2:通过竖向列举法定义数组元素并批量打印。

[root@zabbix 0514]# cat array_menu.sh 
#!/bin/bash
array=(
oldboy
oldgirl
moox
tingting
)
for ((i=0;i<${#array[*]};i++))
do
    echo "this is num $i ,content: ${array[$i]}"
done
echo -----------------------------
echo "array length: ${#array[*]}"


===================================
[root@zabbix 0514]# sh array_menu.sh 
this is num 0 ,content: oldboy
this is num 1 ,content: oldgirl
this is num 2 ,content: moox
this is num 3 ,content: tingting
-----------------------------
array length: 4

范例13-3:将命令结果作为数组元素定义并打印。

[root@zabbix 0514]# ll array
total 0
-rw-r--r-- 1 root root 0 May 14 11:19 1.txt
-rw-r--r-- 1 root root 0 May 14 11:19 2.txt
-rw-r--r-- 1 root root 0 May 14 11:19 3.txt
[root@zabbix 0514]# cat array_ls.sh 
#!/bin/bash
dir=($(ls array))				==> 将ls的结果放到数组中,数组定义:array=(1 2 3 ..)
								==> $(ls array) =  `ls array`
for ((i=0;i<${#dir[*]};i++))
do
    echo "NO.$i : ${dir[$i]}"
done
[root@zabbix 0514]# sh array_ls.sh 
NO.0 : 1.txt
NO.1 : 2.txt
NO.2 : 3.txt

13.4 shell 数组的重要命令

(1)定义命令

1.静态数组   array=(1 2 3)
2.动态数组	 array=($(ls))或array=(`ls`)
3.数组赋值	 array[2]=3

(2)打印命令

1.打印所有元素   ${array[@]} 或 ${array[*]}
2.打印数组长度   ${#array[@]} 或 ${#array[*]}
3.打印单个元素   ${array[i]}

(3)循环打印的常用基本语法

#!/bin/bash
array={
    10.0.0.11
    10.0.0.22
    10.0.0.33
}
==> C语言for循环语法
for ((i=0;i<${#array[*]};i++))
do
	echo ${array[$i]}
done
==>普通for循环语法
for  n  in ${array[*]}
do
	echo $n
done

13.5 shell数组相关面试题及实战案例

13.5.1 数组实现循环打印单词

范例13-4:利用bash for循环打印下面这句话中字母数不大于6的单词(某企业面试真题)。

I am oldboy training  welcome to my linux class

方法1:通过数组方法来实现。

[root@zabbix 0515]# cat array_length.sh 
#!/bin/bash
arr=(I am oldboy training  welcome to my linux class )
for ((i=0;i<${#arr[*]};i++))
do
    if [ ${#arr[$i]} -lt 6 ];then
       echo ${arr[$i]}
    fi
done
echo ------------------------
for word in ${arr[*]}
do
    if [ `expr length $word` -lt 6 ]
      then
	echo $word
    fi
done

方法2:使用for循环列举取值列表法。

[root@zabbix 0515]# cat array_length.sh 
#!/bin/bash
#for word in I am oldboy training  welcome to my linux class 
chars="I am oldboy training  welcome to my linux class" 
for word in $chars
do
    if [ `echo $word|wc -L` -lt 6 ]
      then
	echo $word
    fi
done

方法3:通过awk循环实现。

[root@zabbix 0515]# chars="I am oldboy training  welcome to my linux class"
[root@zabbix 0515]# echo $chars |awk '{for(i=1;i<=NF;i++)if(length($i)<=6) print $i}'
I
am
oldboy
to
my
linux
class

13.5.2 数组实现批量检查多个网址异常

范例13-5:批量检查多个网站地址是否正常。

要求:
1)使用Shell数组的方法实现,检测策略尽量模拟用户访问。
2)每10秒进行一次全部检测,无法访问的输出报警。
3)待检测的地址如下。
http://blog.moox.com
http://blog.moox.org
http://www.moox.com
http://10.0.0.71

解题思路:
1)把URL定义成数组,形成函数。
2)编写URL检查脚本函数,传入数组的元素,即URL。
3)组合实现整个案例,编写main主函数(即执行函数),每隔10秒检查一次。
下面的参考答案采用了Shell数组的方法,同时检测多个URL是否正常,并给出专业的展示效果

[root@zabbix 0515]# cat array_url.sh 
#!/bin/bash
. /etc/init.d/functions

check_count=0
url_list=(
http://blog.moox.com
http://blog.moox.org
http://www.moox.com
http://10.0.0.71
)
function wait(){
    echo -n "3 second  later , check url would be run."
    for ((i=3;i>=1;i--))
    do
	echo -n " $i " 
	sleep 1
    done
}
function check_url(){
    wait
    for ((i=0;i<`echo ${#url_list[*]}`;i++))
    do
	wget -o /dev/null -T 3 --tries=1 --spider ${url_list[$i]} > /dev/null 2>&1
	if [ $? -eq 0 ];then
	    action $"${url_list[$i]}" /bin/true
	else
	    action $"${url_list[$i]}" /bin/false
	fi
    done
    ((check_count++))
}
function main(){
    while true
    do
	check_url
	echo "--------check count: ${check_count}"
	sleep 10
    done
}
main 

13.6 合格运维人员必会的脚本列表

作为一个合格的运维人员,需要掌握的脚本知识列表如下:
1)系统及各类服务的监控脚本,例如:文件、内存、磁盘、端口,URL监控报警等。
2)监控网站目录下的文件是否被篡改,以及当站点目录被批量篡改后如何批量恢复它们的脚本。
3)各类服务Rsync、Nginx、MySQL等的启动及停止专业脚本(使用chkconfig管理)。
4)MySQL主从复制监控报警,以及自动处理不复制故障的脚本。
5)一键配置MySQL多实例、一键配置MySQL主从部署的脚本。
6)监控HTTP、MySQL、Rsync、NFS、Memcached等服务是否异常的生产脚本。
7)一键软件安装及优化的脚本,比如LANMP、Linux一键优化,一键数据库安装、优化等。
8)MySQL多实例启动脚本,分库、分表自动备份脚本。
9)根据网络连接数及Web日志PV数封IP的脚本。
10)监控网站的PV及流量,并且对流量信息进行统计的脚本。
11)检查Web服务器多个URL地址是否异常的脚本,要是可以批量处理且通用的脚本。
12)对系统的基础配置一键优化的脚本。
13)TCP连接状态及IP统计报警的脚本。
14)批量创建用户并设置随机8位密码的脚本。

posted on 2020-05-15 18:12  zhangfd  阅读(413)  评论(0编辑  收藏  举报