zoukankan      html  css  js  c++  java
  • Shell编程之for和select循环

    一、for和select循环

    1.for循环语法

    for 变量名 in 变量取值列表
    do
    	指令...
    done
    

    C语言型for循环

    for ((exp1; exp2; exp3))
    do
    	指令...
    done
    

    示例:

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

    说明:

    • 第一个是变量初始化
    • 第二个是变量范围
    • 第三个是变量自增或自减

    2.for循环实践

    (1)打印5、4、3、2、1这5个数字

    [root@codis-178 ~]# cat 11_1.sh 
    #!/bin/bash
    for num in 5 4 3 2 1
    do
    	echo $num
    done
    [root@codis-178 ~]# sh 11_1.sh 
    5
    4
    3
    2
    1
    
    其他方式:
    [root@codis-178 ~]# cat 11_1_1.sh 
    #!/bin/bash
    for num in {5..1}
    do
    	echo $num
    done
    

    (2)获取当前目录下的目录或文件,并将其作为变量列表打印输出

    [root@codis-178 ~]# mkdir -p /test/{text.txt,oldboy.txt,oldgirl.txt}
    [root@codis-178 ~]# ls -l /test/
    total 12
    drwxr-xr-x 2 root root 4096 Aug 23 10:42 oldboy.txt
    drwxr-xr-x 2 root root 4096 Aug 23 10:42 oldgirl.txt
    drwxr-xr-x 2 root root 4096 Aug 23 10:42 text.txt
    
    
    [root@codis-178 ~]# cat 11_2.sh 
    #!/bin/bash
    cd /test
    for filename in `ls`
    do
    	echo $filename
    done
    [root@codis-178 ~]# sh 11_2.sh 
    oldboy.txt
    oldgirl.txt
    text.txt
    

    (3)用for循环批量修改文件扩展名(把txt改成jpg)

    [root@codis-178 ~]# cat 11_3.sh 
    #!/bin/bash
    cd /test
    for filename in `ls|grep "txt$"`
    do
    	mv $filename `echo $filename|cut -d . -f1`.jpg
    done
    [root@codis-178 ~]# sh 11_3.sh 
    [root@codis-178 ~]# ls -l /test/
    total 12
    drwxr-xr-x 2 root root 4096 Aug 23 10:42 oldboy.jpg
    drwxr-xr-x 2 root root 4096 Aug 23 10:42 oldgirl.jpg
    drwxr-xr-x 2 root root 4096 Aug 23 10:42 text.jpg
    
    简介方法:
    [root@codis-178 ~]# rename "jpg" "gif" /test/*.jpg
    [root@codis-178 ~]# ls -l /test/
    total 12
    drwxr-xr-x 2 root root 4096 Aug 23 10:42 oldboy.gif
    drwxr-xr-x 2 root root 4096 Aug 23 10:42 oldgirl.gif
    drwxr-xr-x 2 root root 4096 Aug 23 10:42 text.gif
    

    3.企业应用

    (1)批量修改文件名,去掉"_finished"

    sed版
    [root@codis-178 ~]# cat 11_4.sh 
    #!/bin/bash
    cd /test
    for file in `ls *.log`
    do
    	mv $file `echo $file|sed 's/_finished//g'`
    done
    [root@codis-178 ~]# sh 11_4.sh 
    [root@codis-178 ~]# ll /test/*.log
    -rw-r--r-- 1 root root 0 Aug 23 11:03 /test/sku_102999_1.log
    -rw-r--r-- 1 root root 0 Aug 23 11:03 /test/sku_102999_2.log
    -rw-r--r-- 1 root root 0 Aug 23 11:03 /test/sku_102999_3.log
    -rw-r--r-- 1 root root 0 Aug 23 11:03 /test/sku_102999_4.log
    -rw-r--r-- 1 root root 0 Aug 23 11:03 /test/sku_102999_5.log
    
    rename版
    rename "_finished' "' *.jpg
    

    (2)在生产环境下,批量去掉测试数据所用的bd字符

    [root@codis-178 test]# ll
    total 0
    -rw-r--r-- 1 root root 0 Aug 23 11:09 bd502.html
    -rw-r--r-- 1 root root 0 Aug 23 11:09 bd503.html
    -rw-r--r-- 1 root root 0 Aug 23 11:09 bd504.html
    [root@codis-178 test]# rename "bd" "" *.html
    [root@codis-178 test]# ll
    total 0
    -rw-r--r-- 1 root root 0 Aug 23 11:09 502.html
    -rw-r--r-- 1 root root 0 Aug 23 11:09 503.html
    -rw-r--r-- 1 root root 0 Aug 23 11:09 504.html
    

    (3)通过脚本实现仅sshd、rsyslog、crond、network、sysstat服务在开机时启动

    方法一:
    for oldboy in `chkconfig --list|grep "3:on"|awk '{print $1}'|grep -vE "crond|network|sshd|rsyslog|sysstat"`;do chkconfig $oldboy off;done
    
    方法二:
    chkconfig --list|grep -vE "crond|network|sshd|rsyslog|sysstat"|awk '{print "chkconfig " $1 " off"}'|bash
    

    (4)打印九九乘法表

    [root@codis-178 ~]# cat 11_5.sh
    #!/bin/bash
    COLOR='E[47;30m'
    RES='E[0m'
    
    for num1 in `seq 9`
    do
    	for num2 in `seq 9`
    	do
    		if [ $num1 -ge $num2 ];then
    			if (((num1*num2)>9))
    				then
    					echo -en "${COLOR}${num1}x${num2}=$((num1*num2))${RES} "
    			else
    				echo -en "${COLOR}${num1}x${num2}=$((num1*num2))${RES}  "
    			fi
    		fi
    	done
    	echo " "
    done
    [root@codis-178 ~]# sh 11_5.sh 
    1x1=1   
    2x1=2  2x2=4   
    3x1=3  3x2=6  3x3=9   
    4x1=4  4x2=8  4x3=12 4x4=16  
    5x1=5  5x2=10 5x3=15 5x4=20 5x5=25  
    6x1=6  6x2=12 6x3=18 6x4=24 6x5=30 6x6=36  
    7x1=7  7x2=14 7x3=21 7x4=28 7x5=35 7x6=42 7x7=49  
    8x1=8  8x2=16 8x3=24 8x4=32 8x5=40 8x6=48 8x7=56 8x8=64  
    9x1=9  9x2=18 9x3=27 9x4=36 9x5=45 9x6=54 9x7=63 9x8=72 9x9=81
    

    (5)计算1到100之和

    [root@codis-178 ~]# cat 11_6.sh
    #!/bin/bash
    for ((i=1;i<=100;i++))
    do
    	((sum=sum+i))
    done
    echo $sum
    [root@codis-178 ~]# sh 11_6.sh
    5050
    

    4.for循环高级应用

    (1)实现MySQL分库备份脚本

    [root@codis-178 ~]# cat 11_7.sh 
    #!/bin/bash
    PATH="/app/mysql/bin:$PATH"
    DBPATH=/server/backup
    MYUSER=root
    MYPASS=oldboy123
    SOCKET=/data/3306/mysql.sock
    MYCMD="mysql -u$MYUSER -p$MYPASS -S $SOCKET"
    MYDUMP="mysqldump -u$MYUSER -p$MYPASS -S $SOCKET"
    [ ! -d "$DBPATH" ] && mkdir $DBPATH
    for dbname in `$MYCMD -e "show databases;"|sed '1,2d'|egrep -v "mysql|schema"`
    do
    	$MYDUMP $dbname|gzip >$DBPATH/${dbname}_$(date +%F).sql.gz
    done
    

    (2)实现MySQL分库分表备份脚本

    批量插入数据
    [root@codis-178 ~]# cat 11_7_1.sh 
    #!/bin/bash
    PATH="/app/mysql/bin:$PATH"
    DBPATH=/server/backup
    MYUSER=root
    MYPASS=oldboy123
    SOCKET=/data/3306/mysql.sock
    MYCMD="mysql -u$MYUSER -p$MYPASS -S $SOCKET"
    MYDUMP="mysqldump -u$MYUSER -p$MYPASS -S $SOCKET"
    for dbname in oldboy oldgirl xiaoting bingbing
    do
    	$MYCMD -e "use $dbname;create table test(id int,name varchar(16)); insert into test values(1,'testdata');"
    done
    
    备份脚本
    [root@codis-178 ~]# cat 11_7_2.sh 
    #!/bin/bash
    PATH="/app/mysql/bin:$PATH"
    DBPATH=/server/backup
    MYUSER=root
    MYPASS=oldboy123
    SOCKET=/data/3306/mysql.sock
    MYCMD="mysql -u$MYUSER -p$MYPASS -S $SOCKET"
    MYDUMP="mysqldump -u$MYUSER -p$MYPASS -S $SOCKET"
    [ ! -d "$DBPATH" ] && mkdir $DBPATH
    for dbname in `$MYCMD -e "show databases;"|sed '1,2d'|egrep -v "mysql|schema"`
    do
    	mkdir $DBPATH/${dbname}_$(date +%F) -p
    	for table in `$MYCMD -e "show tables from $dbname;"|sed '1d'`
    	do
    		$MYDUMP $dbname $table|gzip >$DBPATH/${dbname}_$(date +%F)/${dbname}_${table}.sql.gz
    	done
    done
    

    (3)批量检查Web服务是否正常,并发送相关邮件或手机报警

    [root@codis-178 ~]# cat 11_8.sh 
    #!/bin/bash
    path=/server/scripts
    MAIL_GROUP="1111@qq.com 2222@qq.com"
    PAGER+GROUP="18600338340 18911718229"
    LOG_FILE="/tmp/web_check.log"
    
    [ ! -d "$path" ] && mkdir -p $path
    function UrlList(){
    	cat >$path/domain.list<<EOF
    	http://www.baidu.com
    	http://www.163.com
    	http://www.sina.com
    EOF
    }
    function CheckUrl(){
    	FAILCOUNT=0
    	for ((i=1;$i<=3;i++))
    	do
    		wget -T 5 --tries=1 --spider $1 >/dev/null 2>&1
    
    		if [ $? -ne 0 ];then
    			let FAILCOUNT+=1
    		else
    			break
    		fi
    	done
    	return $FAILCOUNT
    }
    
    function MAIL(){
    	local SUBJECT_CONTENT=$1
    	for MAIL_USER in `echo $MAIL_FROUP`
    	do
    		mail -s "$SUBJECT_CONTENT " $MAIL_USER <$LOG_FILE
    	done
    }
    function PAGER(){
    	for PAGER_USER in `echo $PAGER_GROUP`
    	do
    		TITLE=$1
    		CONTACT=$PAGER_USER
    		HTTPGW=http://oldboy.sms.cn/smsproxy/sendsms.action
    		curl -d cdkey=5ADF-EFA -d password=OLDBOY -d phone=$CONTACT -d message="$TITLE[$2]" $HTTPGW
    	done
    }
    function SendMsg(){
    	if [ $1 -ge 3 ];then
    		RETVAL=1
    		NOW_TIME=`date +%Y-%m-%d %H:%M:%S`
    		SUBJECT_CONTENT="http://$2 is error,${NOW_TIME}"
    		echo -e "$SUBJECT_CONTENT" |tee $LOG_FILE
    		MAIL $SUBJECT_CONTENT
    		PAGER $SUBJECT_CONTENT $NOW_TIME
    	else
    		echo "http://$2 is ok"
    		RETVAL=0
    	fi
    	return $RETVAL
    }
    function main(){
    	UrlList
    	for url in `cat $path/domain.list`
    	do
    		CheckUrl $url
    		SendMsg $? $url
    	done
    }
    main
    

    (4)批量建10个账号,并设置密码(随机数,但必须是字符和数字混合)

    [root@codis-178 ~]# cat 11_9.sh 
    #!/bin/bash
    . /etc/init.d/functions
    user="xiaoda01"
    passfile="/tmp/user.log"
    for num in `seq -w 10`
    do
    	pass="`echo "test$RANDOM"|md5sum|cut -c 3-11`"
    	useradd $user$num &>/dev/null &&
    	echo -e "$user${num}:$pass" >>$passfile
    	if [ $? -eq 0 ];then
    		action "$user$num is ok" /bin/true
    	else
    		action "$user$num is fail" /bin/false
    	fi
    done
    echo -------------------------------
    chpasswd < $passfile
    cat $passfile && >$passfile
    [root@codis-178 ~]# sh 11_9.sh 
    xiaoda0101 is ok                                           [  OK  ]
    xiaoda0102 is ok                                           [  OK  ]
    xiaoda0103 is ok                                           [  OK  ]
    xiaoda0104 is ok                                           [  OK  ]
    xiaoda0105 is ok                                           [  OK  ]
    xiaoda0106 is ok                                           [  OK  ]
    xiaoda0107 is ok                                           [  OK  ]
    xiaoda0108 is ok                                           [  OK  ]
    xiaoda0109 is ok                                           [  OK  ]
    xiaoda0110 is ok                                           [  OK  ]
    -------------------------------
    xiaoda0101:1d2311ee7
    xiaoda0102:cfa830b4d
    xiaoda0103:82920ccf0
    xiaoda0104:c74f8c425
    xiaoda0105:f54760e68
    xiaoda0106:e6d4d939d
    xiaoda0107:364ca359e
    xiaoda0108:3d1a8afb0
    xiaoda0109:c7709971b
    xiaoda0110:6d8ab529c
    

    二、随机数生成方法

    1.系统变量$RANDOM(0~32767)

    [root@codis-178 ~]# echo $RANDOM
    11639
    [root@codis-178 ~]# echo $RANDOM
    26729
    

    2.通过openssl产生

    [root@codis-178 ~]# openssl rand -base64 8
    093jnyH8wW0=
    [root@codis-178 ~]# openssl rand -base64 16
    wbdEcXUylW09GcQZdPfumQ==
    [root@codis-178 ~]# openssl rand -base64 16
    mj2ZsMWN5kGcAxG/uvyeBw==
    

    3.通过时间date

    [root@codis-178 ~]# date +%s%N
    1503467625592127445
    [root@codis-178 ~]# date +%s%N
    1503467628842171721
    

    4.通过/dev/urandom配合cksum

    [root@codis-178 ~]# head /dev/urandom |cksum 
    3335560219 3028
    [root@codis-178 ~]# head /dev/urandom |cksum 
    1646715305 2885
    

    说明:
    /dev/urandom设备存储着系统当前运行环境的实时数据,可以看作系统在某个时候的唯一值。

    5.通过UUID

    [root@codis-178 ~]# cat /proc/sys/kernel/random/uuid 
    92062c1c-ccc3-4d4d-939a-827b6f93f3d9
    [root@codis-178 ~]# cat /proc/sys/kernel/random/uuid 
    5a274f33-ad1c-4ad1-bc86-d6b472dec70a
    [root@codis-178 ~]# cat /proc/sys/kernel/random/uuid 
    7178879c-fcf7-4acb-8b43-5936bc403336
    

    说明:
    UUID码是通用唯一识别码,是一个软件建构的标准,目的是让分布式系统中的所有元素都能有唯一的辨识信息。

    6.使用expect附带的mkpasswd

    usage: mkpasswd [args] [user]
      where arguments are:
        -l #      (length of password, default = 9)  密码长度
        -d #      (min # of digits, default = 2)  数字的数量
        -c #      (min # of lowercase chars, default = 3)  小写字母的数量
        -C #      (min # of uppercase chars, default = 2)  大写字母的数量
        -s #      (min # of special chars, default = 1)  特殊字符的数量
        -v        (verbose, show passwd interaction)
        -p prog   (program to set password, default = passwd)
    	
    [root@codis-178 ~]# mkpasswd -l 16 -d 4 -c 4 -C 4 -s 4
    04r-v3"zIa5G??LC
    [root@codis-178 ~]# mkpasswd -l 16 -d 4 -c 4 -C 4 -s 1
    HHldb8zZJ%0mh00r
    [root@codis-178 ~]# mkpasswd -l 16 -d 4 -c 4 -C 4 -s 4
    D#uC{1#17kVyjM2
    

    总结

    统一格式化:使用md5sum|cut -c 2-10

    三、select循环

    1.select语法

    select 变量名 [ in 菜单取值列表 ]
    do
    	指令...
    done
    

    l00

    2.select循环的作用

    创建菜单

    3.实现

    [root@codis-178 ~]# cat 11_10.sh 
    #!/bin/bash
    select name in oldboy oldgirl tingting
    do
    	echo $name
    done
    [root@codis-178 ~]# sh 11_10.sh 
    1) oldboy
    2) oldgirl
    3) tingting
    #? 1
    oldboy
    #? 2
    oldgirl
    #? 3
    tingting
    

    调整select菜单项的默认提示符及利用select变量打印数字序号

    [root@codis-178 ~]# cat 11_10_1.sh 
    #!/bin/bash
    PS3="please select a num from menu:"
    select name in oldboy oldgirl tingting
    do
    	echo -e "I guess you selected the menu is:
     $REPLY) $name"
    done
    [root@codis-178 ~]# sh 11_10_1.sh 
    1) oldboy
    2) oldgirl
    3) tingting
    please select a num from menu:1
    I guess you selected the menu is:
     1) oldboy
    please select a num from menu:2
    I guess you selected the menu is:
     2) oldgirl
    please select a num from menu:3
    I guess you selected the menu is:
     3) tingting
    
  • 相关阅读:
    CodeForces 660D Number of Parallelograms
    【POJ 1082】 Calendar Game
    【POJ 2352】 Stars
    【POJ 2481】 Cows
    【POJ 1733】 Parity Game
    【NOI 2002】 银河英雄传说
    【NOI 2015】 程序自动分析
    【POJ 1704】 Georgia and Bob
    【HDU 2176】 取(m堆)石子游戏
    【SDOI 2016】 排列计数
  • 原文地址:https://www.cnblogs.com/tongxiaoda/p/7454647.html
Copyright © 2011-2022 走看看