Shell 数组实践

Shell 数组实践


Shell 数组介绍

为什么会产生 Shell 数组

  1. 开发 Shell 脚本时,定义变量通常采用 var=value 的形式。若有多个变量要定义,逐个定义会很麻烦:
bash 复制代码
a=1
b=2
c=3
  1. 快速读取不同变量的值也是一件很痛苦的事情。

什么是 Shell 数组

简单地说,Shell 数组就是一个元素集合:把有限个元素(变量或字符内容)用一个名字命名,用编号区分。这个名字称为数组名 ,编号称为数组下标 ,各个元素称为数组元素(也称下标变量)。

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


Shell 数组的基本操作

Shell 数组的定义

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

方法 1:括号赋值(推荐)

用小括号将变量值括起来赋值给数组变量,每个变量值之间用空格分隔。

语法:

bash 复制代码
array=(value1 value2 value3 ...)

此为常用定义方法,需要重点掌握。

示例:

bash 复制代码
# 用小括号将数组内容赋值给数组变量,数组元素用空格分隔
[rich@rich-shell ~]$ array=(1 2 3)

# 输出数组所有元素值
[rich@rich-shell ~]$ echo ${array[*]}
1 2 3

# 数组变量下标从 0 开始
[rich@rich-shell ~]$ echo ${array[0]}
1
方法 2:键值对赋值(不推荐)

用小括号括起来,同时采用键值对形式赋值。

语法:

bash 复制代码
array=([1]=one [2]=two [3]=three)

小括号里对应的数字为数组下标,等号后面为下标对应的值。此方法较复杂,不推荐使用。

示例:

bash 复制代码
[rich@rich-shell ~]$ array=([0]=one [1]=two [2]=three)

[rich@rich-shell ~]$ echo ${array[*]}
one two three

[rich@rich-shell ~]$ echo ${array[0]}
one

[rich@rich-shell ~]$ echo ${array[1]}
two
方法 3:逐元素赋值(不推荐)

通过分别定义数组变量的方法来定义。

语法:

bash 复制代码
array[0]=a
array[1]=b
array[2]=c

此种定义方法比较麻烦,不推荐使用。

示例:

bash 复制代码
[rich@rich-shell ~]$ array[0]=a
[rich@rich-shell ~]$ array[1]=b
[rich@rich-shell ~]$ array[2]=c
[rich@rich-shell ~]$ echo ${array[0]}
a
方法 4:命令输出作为数组内容

动态定义数组变量,使用命令的输出结果作为数组内容。

语法:

bash 复制代码
array=($(命令))
# 或者
array=(`命令`)

示例:

bash 复制代码
[rich@rich-shell ~]$ sudo mkdir /array
[rich@rich-shell ~]$ sudo touch /tmp/file-{1..3}.txt
[rich@rich-shell ~]$ array=($(ls /tmp/file*.txt))
[rich@rich-shell ~]$ echo ${array[*]}
/tmp/file-1.txt /tmp/file-2.txt /tmp/file-3.txt

Shell 数组其他操作

打印数组变量值
bash 复制代码
[rich@rich-shell ~]$ array=(a b c d)

# 打印数组第一个元素值
[rich@rich-shell ~]$ echo ${array[0]}
a

# 打印数组所有元素
[rich@rich-shell ~]$ echo ${array[*]}
a b c d

[rich@rich-shell ~]$ echo ${array[@]}
a b c d

${array[*]}${array[@]} 在双引号内行为不同;不加引号时效果通常等同。

打印数组元素的个数
bash 复制代码
# 以下两种方式效果等同
[rich@rich-shell ~]$ echo ${#array[*]}
4

[rich@rich-shell ~]$ echo ${#array[@]}
4

竖向定义数组(多行更清晰):

bash 复制代码
[rich@rich-shell ~]$ array=(
    linux
    mysql
    httpd
    python
)
数组赋值

可直接通过「数组名[下标]」对数组引用赋值:下标不存在则自动添加新元素;下标存在则覆盖原值。

bash 复制代码
# 下标不存在,添加新元素
[rich@rich-shell ~]$ array[5]=6
[rich@rich-shell ~]$ echo ${array[*]}
1 b c d 6

# 下标 4 的第 5 个元素未定义
[rich@rich-shell ~]$ echo ${array[4]}

[rich@rich-shell ~]$ echo ${array[5]}
6

# 下标存在,覆盖原值
[rich@rich-shell ~]$ array[0]=1
数组的删除

数组本质上仍是变量,可通过 unset 清除元素或整个数组。

bash 复制代码
[rich@rich-shell ~]$ echo ${array[*]}
1 b c d

# 删除整个数组
[rich@rich-shell ~]$ unset array
[rich@rich-shell ~]$ echo ${array[*]}

# 删除指定下标元素
[rich@rich-shell ~]$ unset array[5]
[rich@rich-shell ~]$ echo ${array[5]}
数组内容截取

与变量子串的替换提取相同,因为数组是特殊的变量。

bash 复制代码
[rich@rich-shell ~]$ array=(a b c d e)

# 截取下标 1--3 的元素
[rich@rich-shell ~]$ echo ${array[@]:1:3}
b c d

# 截取下标 1 之后的所有元素
[rich@rich-shell ~]$ echo ${array[@]:1}
b c d e
数组内容替换

与变量子串替换相同。

bash 复制代码
[rich@rich-shell ~]$ array=({a..z})
[rich@rich-shell ~]$ 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

# 替换展示,数组内容并未改变
[rich@rich-shell ~]$ echo ${array[@]/b/2}
a 2 c d e f g h i j k l m n o p q r s t u v w x y z

[rich@rich-shell ~]$ 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

# 直接修改数组内容
[rich@rich-shell ~]$ array=(${array[@]/b/2})
[rich@rich-shell ~]$ echo ${array[@]}
a 2 c d e f g h i j k l m n o p q r s t u v w x y z
数组内容删除(模式删除)

与变量子串删除相同,对每个元素分别生效。

bash 复制代码
[rich@rich-shell ~]$ array=(abc123abc123 abcd1234abcd1234)
[rich@rich-shell ~]$ echo ${array[@]}
abc123abc123 abcd1234abcd1234

# 针对每个元素从左删除
[rich@rich-shell ~]$ echo ${array[@]#*c}
123abc123 d1234abcd1234

[rich@rich-shell ~]$ echo ${array[@]##*c}
123 d1234

# 针对每个元素从右删除
[rich@rich-shell ~]$ echo ${array[@]%c*}
abc123ab abcd1234ab

[rich@rich-shell ~]$ echo ${array[@]%%c*}
ab ab

Shell 数组脚本开发实践

示例 1:通过循环打印数组所有元素

C 语言型 for 循环:

bash 复制代码
# array1.sh
#!/bin/bash
array=({a..d})

for (( i=0; i<${#array[@]}; i++ )); do
    echo ${array[i]}
done

执行结果:

text 复制代码
[rich@rich-shell ~]$ bash array1.sh
a
b
c
d

普通 for 循环:

bash 复制代码
# array2.sh
#!/bin/bash
array=({a..d})

for str in ${array[@]}; do
    echo $str
done

while 循环:

bash 复制代码
# array3.sh
#!/bin/bash
array=({a..d})
i=0

while (( i<${#array[@]} )); do
    echo ${array[i]}
    ((i++))
done

例 1:打印字母数不大于 6 的单词

题目句子:

text 复制代码
I am linux teacher welcome to wanho training classroom

脚本 print_words.sh

bash 复制代码
#!/bin/bash
strings=(I am linux teacher welcome to wanho training classroom)
i=0

while (( i<${#strings[@]} )); do
    if [ ${#strings[i]} -le 6 ]; then
        echo ${strings[i]}
    fi
    ((i++))
done

执行结果:

text 复制代码
[rich@rich-shell ~]$ bash print_words.sh
I
am
linux
to
wanho

例 2:批量检查多个网站地址是否正常

使用 Shell 数组实现,检测策略尽量模拟用户访问。每 10 秒进行一次全部检测,无法访问时输出报警。

待检测地址示例:

脚本 check_web.sh

bash 复制代码
#!/bin/bash

url_list=(
    http://www.baidu.com
    http://www.redhat.fun
    http://www.redhat.com
)

function check_url() {
    echo "==========检查站点是否可以访问=========="
    for ((i=0; i<${#url_list[@]}; i++)); do
        echo -n "${url_list[i]}..."
        wget -o /dev/null -T3 --tries=1 --spider ${url_list[i]} &>/dev/null
        [ $? -eq 0 ] && echo "可以访问" || echo "不可以访问"
    done
    echo -e "========================================\n"
    echo -n "==========10秒后再次检查=========="
    sleep 10
    echo -e "\n"
}

function main() {
    while true; do
        check_url
    done
}

main

执行效果:

text 复制代码
[rich@rich-shell ~]$ bash check_web.sh
==========检查站点是否可以访问==========
http://www.baidu.com...可以访问
http://www.redhat.fun...不可以访问
http://www.redhat.com...可以访问
========================================

==========10秒后再次检查==========

==========检查站点是否可以访问==========
http://www.baidu.com...可以访问
http://www.redhat.fun...不可以访问
http://www.redhat.com...可以访问
========================================

==========10秒后再次检查==========^C

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

作为一个合格的运维人员,需要掌握的脚本知识列表如下:

  1. 系统及各类服务的监控脚本,例如:文件、内存、磁盘、端口、URL 监控报警等。
  2. 监控网站目录下的文件是否被篡改,以及站点目录被批量篡改后如何批量恢复的脚本。
  3. 各类服务(Rsync、Nginx、MySQL 等)的启动及停止专业脚本。
  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 位密码的脚本。
相关推荐
XMAIPC_Robot11 小时前
电力设备RK3568/RK3576+FPGA,多系统混合部署Linux+RTOS RT-THREAD,强实时性
linux·运维·fpga开发
aashuii11 小时前
linux测试lsquic
linux·运维·服务器
认真的薛薛11 小时前
Linux运维:Jenkins部署
linux·运维·jenkins
叶半欲缺11 小时前
密码忘记了吗?Linux单用户模式下修改密码!
linux·运维·服务器
handler0111 小时前
【Linux 网络】一文读懂 HTTP 协议
linux·c语言·网络·c++·笔记·网络协议·http
数智工坊11 小时前
【DACS论文阅读】跨域混合采样如何让语义分割模型从合成数据无缝迁移到真实世界
论文阅读·人工智能·算法·机器人·无人机
铅笔小新z11 小时前
【Linux】进程信号
linux·服务器
晓蓝WQuiet11 小时前
vim/linux使用笔记
linux·笔记·vim
And_Ii11 小时前
LeetCode 026. 重排链表
算法·leetcode·链表