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 "\033[47m " #显示白格 else echo -e -n "\033[40m " #显示黑格 fi done echo "" #换行 done
while循环
while中的动作有可能一次都不执行
while语法
while 条件测试 do 命令序列 done
若条件表达式为真,重复执行动作,直到条件表达式为假才结束
do while
do while将动作前置,先执行前置,先执行动作,再判断条件表达式。因此do while中的动作至少执行一次。
do 动作 while (条件表达式)
使用while循环输出数字1到10(升序输出)降序输出
[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