七 循环结构

for循环结构

列表式循环

根据变量的不同取值,重复执行不同序列

for语法格式
for 变量名 in 变量值列表;
do 
    当变量值列表有值赋给变量名时执行的语句块             
done

例子1:

#!/bin/bash
#for i in 1 2 3 4 5 6 7 8 9 10 
#for i in `head /etc/passwd`
for i in `ls /shell/*.sh`
do 
   echo $i
done

192.168.1.1~192.168.1.5主机的ip地址输出到屏幕上

#!/bin/bash
mynet=192168.1.
#for i in 1 2 3 4 5
#for i in `seq 254`
#for i in `30 45`
#for i in `seq 10 2 30`
#for i in {a..z}
for i in {1..10}                     
do 
      echo $mynet$i
done

例子2:

#!/bin/bash
for i in `seq 10`
do 
   if [ `expr $i % 2` -eq 0  ];then
       echo $i
   fi
done

用for循环输出192.168.1.0/24网段内所有主机的ip地址

#!/bin/bash
for I in `seq 1 254`
do echo 192.168.1.$I
done

把自己不能与其通信的本网段的主机的ip地址输出到屏幕上
并统计不能与其通信的主机的个数

#!/bin/bash
j=0
mynet=192.168.1
for i  in `seq 5`
do
  ping -c 3 $mynet.$i &> /dev/null
  if [ $? -ne 0 ];then
      echo "$mynet.$i"
      let j++
  fi
done
echo "不在的主机有 $j 台"

例子3:

#!/bin/bash
mynet=192.168.1
for i  in `seq 5`
do
 (ping -c 3 $mynet.$i &> /dev/null
  if [ $? -ne 0 ];then
      echo "主机 $mynet.$i not line!!!" 
  fi) &
done

注意:

() 把当前的程序放到子shell里执行
 &  把程序置入后台运行

把1-20之间的偶数输出 并统计奇数的个数。

#!/bin/bash
for s in `seq 20`

do
  if [ `expr $s % 2` -eq 0 ];then
     echo $s
     let j++
  fi 
done
echo "共有$j个奇数"

把系统已有的binlog日志文件输出

方法1


#!/bin/bash
mysqldir=/var/lib/mysql
cd $mysqldir
for i in  `cat localhost-bin.index`
do
   binlogname=`basename $i`
   echo $binlogname
done

方法2:

#!/bin/bash
for binlog in `cat /var/lib/mysql/data-bin.index`
do
    echo $binlog
done

方法3:

#!/bin/bash
for binlog in `cat /var/lib/mysql/data-bin.index`
do
   
    binlogname=`basename $binlog`
    echo $binlogname
done      

每天的 23:30 备份当前数据库服务器上新生成的binlog日志文件到系统的/newbinlogdir目录里. (当前正在使用binlog日志文件不备份)

#!/bin/bash
datadir=/var/lib/mysql
bakdir=/mysqlbak
lastbinlogname=`tail -1 $datadir/mysqld-bin.index  | awk  -F"/"  '{print $2}'`

if [ -e $bakdir ];then
    cd $datadir
    for i  in  `cat  mysqld-bin.index `
    do
        binlogname=`basename $i`
        if [ "$binlogname" != "$lastbinlogname" ];then
            if [ ! -e $bakdir/$binlogname ];then
                cp  $binlogname  $bakdir
            else
                echo "$binlogname baked"     
            fi
        else
            echo "$lastbinlogname useeing!!!!"
        fi

    done
else
    mkdir $bakdir
    cd $datadir
    for i  in  `cat  mysqld-bin.index `
    do
        binlogname=`basename $i`
        if [ "$binlogname" != "$lastbinlogname" ];then
            if [ ! -e $bakdir/$binlogname ];then
                cp  $binlogname  $bakdir
            else
                echo "$binlogname baked"     
            fi
        else
            echo "$lastbinlogname useeing!!!!"
        fi
    done
fi

C语言风格的for循环

通过变量控制,条件成立时循环
步长可控次数
for((赋初值;条件判断;步长))

例子:

for((i=5;i==3;i++))
do
   echo $i
   sleep 1
done

使用for循环嵌套实现九九乘法表

#!/bin/bash
#通过for循环嵌套实现九九乘法表,其中temp用于保存i+j的值
for (( i = 1;i <=9; i++ ))
do
    #內层循环
    for (( j=1; j <=i; j++ ))
    do
        let "temp = i * j"   #暂时存储i*j的值
        echo -n "$i*$j=$temp "
    done
    echo ""
done

使用for循环嵌套实现8X8个的棋盘

#!/bin/bash
#外层循环
for (( i = 1;i <=8; i++ ))
do
  #內层循环
    for (( j=1; j <=8; j++ ))
    do
    #下面两行用于不重叠显示黑白格
        total=$(( $i + $j ))
        tmp=$(( $total % 2 )) 
        if [ $tmp -eq 0 ];
        then
            echo -e -n "33[47m "   #显示白格
        else 
            echo -e -n "33[40m "   #显示黑格
        fi
    done
    echo "" #换行
done

while循环

while中的动作有可能一次都不执行

while语法

while 条件测试
do
   命令序列
done

若条件表达式为真,重复执行动作,直到条件表达式为假才结束

do while

do while将动作前置,先执行前置,先执行动作,再判断条件表达式。因此do while中的动作至少执行一次。

do
  动作  
while (条件表达式)

使用while循环输出数字110(升序输出)降序输出

[root@localhost shell]# cat while10.sh
#!/bin/bash
j=1
while [ $j -le 10 ]
do 
   echo $j
    let j++ #j=j+1
done

批量添加10个系统用户要求如下:

1、用户的密码与用户名相同

2、用户的前缀是user

3、强制新添加的用户首登录系统时,重置自己的登录系统的密码。

4、编写脚本userdel.sh (删除刚才批量添加的10个系统用户)

 计算100以内所有正整数的和

#!/bin/bash
declare -i I=1
declare -i SUM=0

while [ $I -le 100 ]; do
  let SUM+=$I
  let I++
done
echo $SUM

 练习转换用户输入的字符为大写除了quit:

#!/bin/bash
#
read -p "Input something: " STRING

while [ $STRING != 'quit' ]; do
  echo $STRING | tr 'a-z' 'A-Z'
  read -p "Input something: " STRING
done

练习:每隔5秒查看hadoop用户是否登录,如果登录,显示其登录并退出;否则,显示当前时间,并说明hadoop尚未登录:

 

#!/bin/bash
#
who | grep "hadoop" &> /dev/null
RETVAL=$?

while [ $RETVAL -ne 0 ]; do
  echo "`date`, hadoop is not log." 
  sleep 5
  who | grep "hadoop" &> /dev/null
  RETVAL=$?
done

echo "hadoop is logged in."

写一个脚本:

1. 显示一个菜单给用户:

d|D) show disk usages.

m|M) show memory usages.

s|S) show swap usages.

*) quit.

2 当用户给定选项后显示相应的内容; 

扩展:

当用户选择完成,显示相应信息后,不退出;而让用户再一次选择,再次显示相应内容;除了用户使用quit

#!/bin/bash
#
cat << EOF
d|D) show disk usages.
m|M) show memory usages.
s|S) show swap usages.
*) quit.
EOF

read -p "Your choice: " CHOICE
while [ $CHOICE != 'quit' ];do
  case $CHOICE in
  d|D)
    echo "Disk usage: "
    df -Ph ;;
  m|M)
    echo "Memory usage: "
    free -m | grep "Mem" ;;
  s|S)
    echo "Swap usage: "
    free -m | grep "Swap" ;;
  *)
    echo "Unknown.." ;;
  esac

read -p "Again, your choice: " CHOICE
done    

until循环结构

 与while的执行条件相反
当条件不成立时,循环执行语句序列

语法:

until 条件判断表达式
do 
    循环体
 done

 例子:

until [1 -eq 1 ]      #条件一直成立,会一直执行循环体,就是死循环
do  
   echo "test1"
   sleep   1
done

auto_check_gw.sh 自动切换网关脚本

 case分支语句

检查变量的实际取值
如果与预设的值相匹配,则执行对应的操作

语法:

case 变量名 in 
    模式1)
           变量的值与模式1匹配时执行的操作;;
    模式2)
            变量的值与模式2匹配时执行的操作;;
     模式N)
             变量的值与模式N匹配时执行的操作;;
*)
    变量的值与以上所有模式都不匹配时执行的操作;;
esac

case通常和函数一起使用,用来给服务写启动脚本。

只接受参数start,stop,restart,status其中之一

#!/bin/bash
#
DEBUG=0
ADD=0
DEL=0

for I in `seq 0 $#`; do
  if [ $# -gt 0 ]; then
      case $1 in
      -v|--verbose)
        DEBUG=1
        shift ;;
      -h|--help)
        echo "Usage: `basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
        exit 0
        ;;
      --add)
        ADD=1
        ADDUSERS=$2
        shift 2
        ;;
      --del)
        DEL=1
        DELUSERS=$2
        shift 2
        ;;
      *)
        echo "Usage: `basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
        exit 7
        ;;
    esac
  fi
done

if [ $ADD -eq 1 ]; then
  for USER in `echo $ADDUSERS | sed 's@,@ @g'`; do
    if id $USER &> /dev/null; then
      [ $DEBUG -eq 1 ] && echo "$USER exists."
    else
      useradd $USER
      [ $DEBUG -eq 1 ] && echo "Add user $USER finished."
    fi
  done
fi

if [ $DEL -eq 1 ]; then
  for USER in `echo $DELUSERS | sed 's@,@ @g'`; do
    if id $USER &> /dev/null; then
      userdel -r $USER
      [ $DEBUG -eq 1 ] && echo "Delete $USER finished."
    else
      [ $DEBUG -eq 1 ] && echo "$USER not exist."
    fi
  done
fi

一个脚本showlogged.sh其用法格式为

showlogged.sh -v -c -h|--help

其中,-h选项只能单独使用,用于显示帮助信息;-c选项时,显示当前系统上登录的所有用户数;如果同时使用了-v选项,则既显示同时登录的用户数,又显示登录的用户的相关信息;如

Logged users: 4. 

They are:
root     tty2         Feb 18 02:41
root     pts/1        Mar  8 08:36 (172.16.100.177)
root     pts/5        Mar  8 07:56 (172.16.100.177)
hadoop   pts/6        Mar  8 09:16 (172.16.100.177)

例子:

#!/bin/bash
#
declare -i SHOWNUM=0
declare -i SHOWUSERS=0

for I in `seq 1 $#`; do
  if [ $# -gt 0 ]; then
    case $1 in
    -h|--help)
      echo "Usage: `basename $0` -h|--help -c|--count -v|--verbose"
      exit 0 ;;
    -v|--verbose)
      let SHOWUSERS=1
      shift ;;
    -c|--count)
      let SHOWNUM=1
      shift ;;
    *)
      echo "Usage: `basename $0` -h|--help -c|--count -v|--verbose"
      exit 8 ;;
    esac
  fi
done

if [ $SHOWNUM -eq 1 ]; then
  echo "Logged users: `who | wc -l`."
  if [ $SHOWUSERS -eq 1 ]; then
    echo "They are:"
    who
  fi
fi
原文地址:https://www.cnblogs.com/zhongguiyao/p/8984068.html