【运维必会】shell脚本语言入门(二)!老男孩Linux培训班
老男孩IT教育
技术博客
2022年8月8日 17:17
由于内容篇幅过长,这篇文章接上一篇:【运维必会】shell脚本语言入门!老男孩SRE工程师培训,继续跟着小编来学习吧!
由于内容篇幅过长,这篇文章接上一篇:【运维必会】shell脚本语言入门!老男孩SRE工程师培训,继续跟着小编来学习吧!
流程控制语句
| if判断
语法格式:
单分支: 一个条件一个结果
if [ 条件表达式 ];then
命令的集合
fi
if [ 条件表达式 ]
then
命令的集合
fi
双分支结构: 一个条件 两个结果
if [ 条件表达式 ]
then
执行的命令
else
否则执行什么命令
fi
多分支: 多个条件 多个结果
if [ 条件表达式 ];then
成立执行的命令
elif [ 条件表达式 ];then
成立执行的命令
elif [ 条件表达式 ];then
成立执行的命令
else
以上条件都没匹配到 执行的命令
fi
案例1:根据不同的操作系统版本 安装不同的YUM源
①如何查看操作系统的版本cat /etc/redhat-release
②使用if多分支进行判断
③执行不同的命令
④测试
先写脚本的框架
#!/bin/sh
#更新前进行备份
backup_yum='mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup'
os_version=`cat /etc/redhat-release |awk '{print $(NF-1)}'`
if [ ${os_version%%.*} -eq 7 ];then
$backup_yum
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
elif [ ${os_version%%.*} -eq 6 ];then
$backup_yum
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-6.repo
elif [ ${os_version%%.*} -eq 8 ];then
$backup_yum
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo
fi
完善脚本
#!/bin/sh
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
#更新前进行备份
backup_yum='mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup'
os_version=`cat /etc/redhat-release |awk '{print $(NF-1)}'`
#判断网络是否正常
ping -c1 -W1 developer.aliyun.com &>/dev/null
if [ $? -ne 0 ];then
echo "网络不正常正在重启网卡请稍等...."
systemctl restart network
ping -c1 -W1 developer.aliyun.com &>/dev/null
[ $? -ne 0 ] && echo "请管理员检查网络 sendmail....."
fi
#判断wget是否安装
which wget &>/dev/null
if [ $? -ne 0 ];then
echo "正在安装wget 请稍等....."
yum -y install wget &>/dev/null
[ $? -eq 0 ] && echo "wget 安装成功将继续更新YUM源....."
fi
#根据不同的操作系统版本安装不同的YUM源
if [ ${os_version%%.*} -eq 7 ];then
$backup_yum
echo "正在更新YUM仓库请稍后......."
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo &>/dev/null
if [ $? -eq 0 ];then
action "成功更新阿里云YUM仓库" /bin/true
else
action "更新失败请检查网络" /bin/false
fi
elif [ ${os_version%%.*} -eq 6 ];then
$backup_yum
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-6.repo
elif [ ${os_version%%.*} -eq 8 ];then
$backup_yum
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo
fi
案例2:使用if判断比较两个的数字大小
#!/bin/sh
# 判断num1数字如果是不是纯数字 或者num2不是纯数字 表达式都成立
read -p "请输入两个数字: " num1 num2
if [[ ! $num1 =~ ^[0-9]+$ || ! $num2 =~ ^[0-9]+$ ]];then
echo "请输入整数"
exit
fi
# 比较两数大小
if [ $num1 -gt $num2 ];then
echo "$num1>$num2"
elif [ $num1 -lt $num2 ];then
echo "$num1<$num2"
else
echo "$num1=$num2"
fi
案例3:安装不同的PHP版本
菜单的使用方法
方法一:
# cat menu.sh
#!/bin/sh
echo -e "\t\t\t1.PHP5.4"
echo -e "\t\t\t2.PHP5.5"
echo -e "\t\t\t3.PHP7.1"
echo -e "\t\t\t4.PHP7.3"
方法二:
cat<<EOF
1.PHP5.4
2.PHP5.5
3.PHP7.1
4.PHP7.3
EOF
PHP安装脚本
#!/bin/sh
cat<<EOF
1.PHP5.4
2.PHP5.5
3.PHP7.1
4.PHP7.3
EOF
read -p "请选择要安装的版本的编号或者是PHP版本号:[1|PHP5.4] " num
if [ $num = 1 -o $num = "PHP5.4" ];then
echo "yum -y install PHP5.4........"
elif [ $num = 2 -o $num = "PHP5.5" ];then
echo "yum -y install PHP5.5........"
elif [ $num = 4 -o $num = "PHP7.3" ];then
echo "yum -y install PHP7.3........"
fi
| for循环
语法格式:
for 变量 in 值的列表 值: 数字 字符串 命令 序列 默认以空格来分隔
do
执行的动作 命令的集合
done
输出结果可以和变量相关 也可以不相关
和变量相关:
# cat for.sh
#!/bin/sh
for num in 1 2 3
do
echo $num
done
和变量不相关:
# cat for.sh
#!/bin/sh
for num in 1 2 3
do
echo hehe
done
统计for循环总共循环了多少次:
# cat for.sh
#!/bin/sh
for num in {1..1000}
do
let i++
done
echo $i
for循环 值为命令
输出结果可以和变量相关 也可以不相关
# cat for.sh
#!/bin/sh
for num in `cat /etc/hosts`
do
echo $num
done
for循环案例:
ping 一个c的地址 通表示在线 不通表示离线 10.0.0.1-10.0.0.254
# cat for.sh
#!/bin/sh
for i in {1..254}
do
ping -c 1 10.0.0.${i} &>/dev/null
[ $? -eq 0 ] && echo "10.0.0.${i} 服务器在线" || echo "10.0.0.${i} 服务器不在线"
done
for循环案例: 批量创建用户
#!/bin/sh
read -p "请输入要创建用户的个数: " num
read -p "请输入要创建用户的前缀: " prefix
for i in `seq $num`
do
user=${prefix}$i
id $user &>/dev/null
if [ $? -ne 0 ];then
useradd $user &>/dev/null
[ $? -eq 0 ] && echo "$user 用户创建成功"
else
echo "useradd: user $user already exists"
fi
done
for循环添加和删除用户 不带密版
#!/bin/sh
read -p "请输入用户的个数: " num
read -p "请输入用户的前缀: " prefix
echo "当前输入的用户名为:"
for i in `seq $num`
do
echo "${prefix}$i"
done
read -p "请问您是要删除以上用户还是创建以上用户[del|add]: " re
if [ $re = add ];then
for i in `seq $num`
do
user=${prefix}$i
id $user &>/dev/null
if [ $? -ne 0 ];then
useradd $user &>/dev/null
[ $? -eq 0 ] && echo "$user 用户创建成功"
else
echo "useradd: user $user already exists"
fi
done
elif [ $re = del ];then
for i in `seq $num`
do
user=${prefix}$i
id $user &>/dev/null
if [ $? -eq 0 ];then
userdel -r $user &>/dev/null
[ $? -eq 0 ] && echo "$user 用户删除成功"
else
echo "用户不存在"
fi
done
fi
| while循环
语法结构:
while [ 条件表达式 ] 条件表达式成立(为真)则执行 否则不执行
do
命令
done
使用实例:死循环
方式一:
#!/bin/sh
while true
do
echo hehe
sleep 1
done
方式二:
#!/bin/sh
while [ 10 -gt 5 ]
do
echo hehe
sleep 1
done
方式三:
#!/bin/sh
while [ -f /etc/hosts ]
do
echo hehe
sleep 1
done
while读取文件 取值语法结构:
while read line # line变量名称 自定义
do
执行的命令
done
使用实例:
方式一:
#!/bin/sh
while read line
do
echo $line
done</etc/hosts
方式二:
#!/bin/sh
while read line
do
user=`echo $line|awk '{print $1}'`
useradd $user
pass=`echo $line|awk '{print $2}'`
echo $pass|passwd --stdin $user
done<user.txt
流程控制语句
使用实例:
控制语句exit:
#!/bin/sh
while true
do
echo test.......
exit
echo oldboy.......
done
echo hehe...........
控制语句break:
#!/bin/sh
while true
do
echo test.......
break
echo oldboy.......
done
echo hehe...........
控制语句continue:
#!/bin/sh
while true
do
echo test.......
continue
echo oldboy.......
done
echo hehe...........
流程控制语句案例:
exit 创建完oldboy5用户 退出当前脚本 只能创建5个用户
#!/bin/sh
for i in `seq 5`
do
user=oldboy$i
id $user &>/dev/null
if [ $? -eq 0 ];then
exit
else
useradd $user &>/dev/null
[ $? -eq 0 ] && echo "$user 创建成功"
fi
done
break 创建完oldboy5用户 跳出本层循环继续往下执行 创建5个用户
#!/bin/sh
for i in `seq 5`
do
user=oldboy$i
id $user &>/dev/null
if [ $? -eq 0 ];then
break
else
useradd $user &>/dev/null
[ $? -eq 0 ] && echo "$user 创建成功"
fi
done
echo oldboy
continue 在oldboy1到oldboy5用户已经存在情况下继续向下创建用户
#!/bin/sh
for i in `seq 10`
do
user=oldboy$i
id $user &>/dev/null
if [ $? -eq 0 ];then
continue
else
useradd $user &>/dev/null
[ $? -eq 0 ] && echo "$user 创建成功"
fi
done
echo hehe...................
break等级跳 ,break只会跳出当前层循环
#!/bin/sh
while true
do
echo "第一层"
while true
do
echo 第二层
sleep 1
while true
do
echo 第三层
sleep 1
break 3
echo oldboy.......
done
done
done
echo hehe...........
shell函数
1、函数是命令的集合 完成特定功能的代码块
2、函数代码块 方便复用
3、函数类似变量 只有先定义才能执行
区别:变量不调用也会执行 name=oldboy 函数只有调用才会执行代码
| 函数的定义
#!/bin/sh
fun1(){
echo "函数的第一种定义方式"
}
fun1
function fun2 {
echo "函数的第二种定义方式"
}
fun2
function fun3(){
echo "函数的第三种定义方式"
}
fun3
案例: 菜单
#!/bin/sh
fun1(){
echo -e "\t\t\t\t1.包子"
echo -e "\t\t\t\t2.麻辣烫"
echo -e "\t\t\t\t3.小米粥"
echo -e "\t\t\t\t4.汉堡"
echo -e "\t\t\t\t5.烧烤"
}
fun1
| 函数复用
# cat 1.sh
#!/bin/bash
. /server/scripts/day4/test.sh
fun3
# sh 1.sh
函数的第三种定义方式
# cat test.sh
#!/bin/sh
fun1(){
echo "函数的第一种定义方式"
}
function fun2 {
echo "函数的第二种定义方式"
}
function fun3(){
echo "函数的第三种定义方式"
}
案例: 函数的传参
函数调用在函数名称的后面
fun1 参数1 参数2 参数3 对应函数中的 $1 $2 $3
函数判断文件是否存在
# cat fun.sh
#!/bin/sh
fun1(){
if [ -f $1 ];then
echo "$1 文件存在"
else
echo "$1 文件不存在"
fi
}
fun1 /etc/hosts
# sh fun.sh
/etc/hosts 文件存在
# cat fun.sh
#!/bin/sh
fun1(){
if [ -f $3 ];then
echo "$3 文件存在"
else
echo "$3 文件不存在"
fi
}
fun1 /etc/hosts /etc/passwd /etc/fsttttttt
# sh fun.sh
/etc/fsttttttt 文件不存在
# cat fun.sh
#!/bin/sh
fun1(){
if [ -f $1 ];then
echo "$1 文件存在"
else
echo "$1 文件不存在"
fi
}
fun1 $2
# sh fun.sh /etc/passwd /etc/hosts
/etc/hosts 文件存在
函数可以识别变量
#!/bin/sh
file=$1
fun1(){
if [ -f $file ];then
echo "$file 文件存在"
else
echo "$file 文件不存在"
fi
}
fun1
# sh fun.sh /etc/hosts
/etc/hosts 文件存在
| 函数变量
可以识别全局变量 函数外的都是当前shell的全局变量
只在函数内生效的变量定义
# cat fun.sh
#!/bin/sh
fun1(){
local num=20
for i in `seq $num`
do
total=$[$count+$i]
done
echo "当前运算的结果是: $total"
}
fun1
echo $num
# sh fun.sh
当前运算的结果是: 20
函数的返回值 return
# cat fun.sh
#!/bin/sh
fun1(){
echo 100
return 50
}
result=`fun1`
echo "当前函数的返回值是: " $?
echo "当前函数的执行结果: " $result
# sh fun.sh
当前函数的返回值是: 50
当前函数的执行结果: 100
利用返回值来判断
错误写法
错误写法一:
#!/bin/sh
fun1(){
if [ -f $1 ];then
return 50
else
return 100
fi
}
fun1 $1
[ $? -eq 50 ] && echo "文件存在"
[ $? -eq 100 ] && echo "文件不存在"
错误写法二:
#!/bin/sh
fun1(){
if [ -f $1 ];then
return 50
else
return 100
fi
}
fun1 $1
if [ $? -eq 50 ];then
echo 文件存在
elif [ $? -eq 100 ];then
echo 文件不存在
fi
解决方法:
[ $? -eq 50 ] && echo 文件存在 || echo 文件不存在
if [ $? -eq 50 ];then
echo 文件存在
else
echo 文件不存在
fi
赋值的方式
re=$?
if [ $re -eq 50 ];then
echo 文件存在
elif [ $re -eq 100 ];then
echo 文件不存在
fi
case语句
语法结构:
case 变量 in 变量 直接传参 赋值传参
匹配模式1)
执行的命令集合
;;
匹配模式2)
执行命令集合
;;
匹配模式3)
执行命令集合
;;
*)
无匹配后序列 执行命令集合
esac
案例
# cat case.sh
#!/bin/sh
case $1 in
Shell)
echo shell......
;;
MySQL)
echo MySQL......
;;
Docker)
echo docker......
;;
*)
echo hehe......
esac
# sh case.sh Shell
shell......
# sh case.sh MySQL
MySQL......
# sh case.sh Docker
docker......
或者的使用
# cat case.sh
#!/bin/sh
case $1 in
Shell|1)
echo shell......
;;
MySQL|2)
echo MySQL......
;;
Docker|hehe)
echo docker......
;;
*)
# 匹配不到可以给用户执行提示
echo "Usage: $0 [Shell|MySQL|Docker]"
esac
# sh case.sh 1
shell.....
# sh case.sh hehe
docker......
# sh case.sh Shell
shell......
案例: 使用case写一个菜单 显示系统的登录 负载 磁盘 内存等信息
1、先写菜单:f查看内存、w查看负载、d查看磁盘、l查看登录信息、m显示菜单
2、让用户输入查看的信息read -p 请输入查看的信息的编号:
3、使用case做判断 执行对应的命令
#!/bin/sh
menu(){
cat<<EOF
1.f查看内存
2.w查看负载
3.d查看磁盘
4.l查看登录信息
5.m显示菜单
6.e退出
EOF
}
menu
while true
do
read -p "请输入你想查看的信息的编号或者字母:[1|f|2|w] " num
case $num in
1|f)
clear
free -h
;;
2|w)
clear
uptime
;;
3|d)
clear
df -h
;;
5|m)
clear
menu
;;
6|e)
exit
;;
*)
echo "Usage: $0 [1|f|2|w]"
esac
done
case案例:Nginx启动脚本
Nginx启动两种方式:1种是systemctl管理启动、1种是命令行直接启动以上两种同时只能使用一种启动
命令行的方式
/usr/sbin/nginx启动
/usr/sbin/nginx -s stop 停止
重启不支持 先停止在启动
/usr/sbin/nginx -s reload查看状态 过滤端口或者PID
#!/bin/sh
[ -f /etc/init.d/functions ] && . /etc/init.d/functions
nginx='/usr/sbin/nginx'
Te(){
if [ $? -eq 0 ];then
action "Nginx $1 is" /bin/true
else
action "Nginx $1 is" /bin/false
fi
}
case $1 in
start)
$nginx
Te $1
;;
stop)
$nginx -s stop
Te $1
;;
restart)
$nginx -s stop
sleep 1
$nginx
Te $1
;;
reload)
$nginx -s reload
Te $1
;;
status)
Port=`netstat -tnulp|grep nginx|grep master|grep '\btcp\b'|awk '{print $4}'`
echo "Nginx_Port: $Port"
PID=`ps axu|grep nginx|grep master|awk '{print $2}'`
echo "Nginx_PID: $PID"
;;
*)
echo "Usage $0 [start|stop|restart|reload|status]"
esac
case案例: jumpserver 跳板机
1、菜单显示我们可以登录的服务信息:web01 10.0.0.7、web02 10.0.0.8
2、选择登录的服务器
3、使用case匹配
#!/bin/sh
web01=10.0.0.7
web02=10.0.0.8
MySQL=10.0.0.51
BACKUP=10.0.0.41
NFS=10.0.0.31
menu(){
cat<<EOF
1.web01 10.0.0.7
2.web02 10.0.0.8
3.MySQL 10.0.0.51
4.BACKUP 10.0.0.41
5.NFS 10.0.0.31
6.menu 显示菜单
7.exit 退出
EOF
}
menu
trap "" HUP INT TSTP
while true
do
read -p "请输入你要登录服务器的编号或者主机名称:[1|web01|6显示菜单] " num
case $num in
1|web01)
ssh root@$web01
;;
2|web02)
ssh root@$web02
;;
3|MySQL)
ssh root@$MySQL
;;
4|BACKUP)
ssh root@$BACKUP
;;
5|NFS)
ssh root@$NFS
;;
6|menu)
menu
;;
7|exit)
exit
;;
*)
echo "Usage $0 [1|web01|2|web02]"
esac
done
case案例: jumpserver 跳板机扩展
1、运维开发权限不同:运维:all权限 所有服务器都可以连接 、开发:只能连接web1 web2
2、设置密码 只能失败三次
3、2级菜单 服务器信息
#!/bin/sh
web01=10.0.0.7
web02=10.0.0.8
MySQL=10.0.0.51
BACKUP=10.0.0.41
NFS=10.0.0.31
users(){
cat<<EFO
1.运维
2.开发
3.退出
EFO
}
users
ops(){
cat<<EOF
1.web01 10.0.0.7
2.web02 10.0.0.8
3.MySQL 10.0.0.51
4.BACKUP 10.0.0.41
5.NFS 10.0.0.31
6.menu 显示菜单
7.exit 退出
EOF
}
dev(){
cat<<EOF
1.web01 10.0.0.7
2.web02 10.0.0.8
3.menu 显示菜单
4.exit 退出
EOF
}
trap "echo 别瞎按小心爆炸" HUP INT TSTP
read -p "请输入你的身份: " au
if [ $au = 1 ];then
>/tmp/yunwei.pwd
while true
do
yunwei=`cat /tmp/yunwei.pwd | wc -l`
if [ $yunwei -lt 3 ];then
read -s -p "请输入运维的密码: " pass
if [ $pass = woshiyunwei ];then
echo "登录成功欢迎牛逼的运维!!!"
break
else
echo "密码不正确请重新输入密码"
echo 1 >> /tmp/yunwei.pwd
continue
fi
else
echo "密码错误次数太多,现已退出"
exit
fi
done
ops
while true
do
read -p "请输入你要登录服务器的编号或者主机名称:[1|web01|6显示菜单] " num
case $num in
1|web01)
ssh root@$web01
;;
2|web02)
ssh root@$web02
;;
3|MySQL)
ssh root@$MySQL
;;
4|BACKUP)
ssh root@$BACKUP
;;
5|NFS)
ssh root@$NFS
;;
6|ops)
ops
;;
7|exit)
exit
;;
*)
echo "Usage $0 [1|web01|2|web02]"
esac
done
elif [ $au = 2 ];then
>/tmp/kaifa.pwd
while true
do
kaifa=`cat /tmp/kaifa.pwd | wc -l`
if [ $kaifa -lt 3 ];then
read -s -p "请输入开发的密码: " pass
if [ $pass = woshikaifa ];then
echo "登录成功欢迎小小的开发!!!"
break
else
echo "密码不正确请重新输入密码"
echo 1 >>/tmp/kaifa.pwd
continue
fi
else
echo "密码错误次数太多,现已退出"
exit
fi
done
dev
while true
do
read -p "请输入你要登录服务器的编号或者主机名称:[1|web01|3显示菜单] " num
case $num in
1|web01)
ssh root@$web01
;;
2|web02)
ssh root@$web02
;;
3|dev)
dev
;;
4|exit)
exit
;;
*)
echo "Usage $0 [1|web01|2|web02]"
esac
done
elif [ $au = 3 ];then
exit
fi
shell变量数组
数组的分类
普通数组:只能用数字作为索引
关联数组:数字或者字符串作为索引
数组的结构
类似变量:一个名称对应一个值,一个筐子里面只装了一个水果(苹果)
数组:一个名词对应多个值,一个筐子里面装了很多盒子,每个盒子里有不同的水果
索引:盒子的名称,称为索引也称为下标也称为元素名称
数组的格式
数组名称[索引名称]=元素的值筐子[盒子1]=苹果筐子[盒子2]=梨筐子[盒子3]=黄瓜
普通数组的盒子(索引)从0开始筐子[0]=值
| 普通数组的定义方式
第一种定义方式:按照索引进行定义
array[1]=shell
array[2]=mysql
array[3]=docker
查看数组:按照索引进行查看
# echo ${array[2]}
mysql
# echo ${array[1]}
shell
# echo ${array[3]}
docker
查看数组中所有的值
# echo ${array[*]}
shell mysql docker
# echo ${array[@]}
shell mysql docker
查看数组中所有的索引(下标) 所有的盒子的名称
# echo ${!array[@]}
1 2 3
查看索引的总个数
# echo ${#array[@]}
3
查看系统的普通数组
declare -a
第二种定义方式:使用默认的索引来定义
# array=(shell mysql docker oldboy)
# echo ${array[*]}
shell mysql docker oldboy
# echo ${!array[*]}
0 1 2 3
第三种定义方式:使用自定义索引和默认索引定义
# array=([5]=shell mysql [10]=docker hehe)
# echo ${array[*]}
shell mysql docker hehe
# echo ${!array[*]}
5 6 10 11
第四种定义方式:
# array=(`cat /etc/passwd|awk -F: '{print $1}'`)
# echo ${array[*]}
root bin daemon adm lp sync shutdown halt mail operator games ftp nobody systemd-network dbus polkitd tss abrt sshd postfix test1 test2 test3 test4 test5 zhangsan lisi erdan goudan gousheng baoyi oldboy5 oldboy1 oldboy2 oldboy3 oldboy4 oldboy6 oldboy7 oldboy8 oldboy9 oldboy10 nginx
# echo ${!array[*]}
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| 数组的遍历
# unset array
# array=(10 20 30 40)
# echo ${array[*]}
10 20 30 40
# for i in ${array[*]};do echo $i;done
10
20
30
40
案例
# array=(10.0.0.1 10.0.0.7 10.0.0.254 www.baidu.com)
# for i in ${array[*]};do ping -c1 -W1 $i;done
# cat array.sh
#!/bin/sh
ip=(
10.0.0.1
www.baidu.com
10.0.0.7
10.0.0.8
www.sinaaaa.com
10.0.0.254
www.weibo.com
)
for i in ${ip[*]}
do
ping -c1 -W1 $i &>/dev/null
if [ $? -eq 0 ];then
echo "$i 在线"
else
echo "$i 不在线"
fi
done
使用索引的方式进行遍历
# echo ${array[*]}
10.0.0.1 10.0.0.7
# echo ${!array[*]}
0 1
# echo ${array[0]}
10.0.0.1
# echo ${array[1]}
10.0.0.7
# for i in ${!array[*]};do echo ${array[$i]};done
10.0.0.1
10.0.0.7
| 关联数组
使用字符串作为索引,定义方式:
默认的定义方式是普通数组
# array[index1]=shell
# array[index2]=mysql
# array[index3]=docker
# echo ${array[*]}
docker
# declare -a |grep array
declare -a array='([0]="docker")'
配置关联数组 提前声明 declare -A 声明关联数组
# declare -A array
# array[index1]=shell
# array[index2]=mysql
# array[index3]=redis
# echo ${array[*]}
shell mysql redis
查看索引
echo ${!array[*]}
案例:统计当前的男性和女性出现的次数
# cat sex.txt
m
m
f
m
f
x
# for i in `cat sex.txt`;do let $i++;done
# echo $m
3
# echo $f
2
# echo $x
1
执行过程
#!/bin/sh
declare -A sex
while read line
do
let sex[$line]++
line=m
let sex[m]++
line=x
let sex[x]++
line=f
let sex[f]++
done<sex.txt
直接查看
#!/bin/sh
declare -A sex
while read line
do
let sex[$line]++
done<sex.txt
echo m 出现了 ${sex[m]} 次
echo f 出现了 ${sex[f]} 次
echo x 出现了 ${sex[x]} 次
数组遍历
#!/bin/sh
declare -A sex
while read line
do
let sex[$line]++
done<sex.txt
for i in ${!sex[*]}
do
echo $i 出现了 ${sex[$i]} 次
done
案例: 统计nginx日志每个IP出现的次数
#!/bin/sh
declare -A ip
while read line
do
let ip[`echo $line|awk '{print $1}'`]++
done</var/log/nginx/access.log
for i in ${!ip[*]}
do
echo $i 出现了 ${ip[$i]} 次
done