老男孩教育专注IT教育10余年,只培养IT技术精英

全国免费咨询电话(渠道合作):400-609-2893

【运维必会】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

 

本文经授权发布,不代表老男孩教育立场。如若转载请联系原作者。