循环
1. 循环语句语法 (1) for循环 for variable in varlist do statement done 或C语言类型的循环 for((exp1;exp2;exp3)) do statement done (2) while循环 while condition do statement done (3) until循环 while condition do statement done (4) 使用$0循环 #!/bin/bash clear date "+%Y-%m-%d %H:%M:%S" sleep 1 sh $0 ----------------------- 循环次数较少可以使用 (5) 跳出循环 break、continue、exit continue --跳过某一个条件,继续执行其他循环 break --跳出循环,不再循环,往下执行代码 exit --退出程序 exit退出时可以返回一个状态信息,范围是0-255,一般情况0是正常退出。 #!/bin/bash for (( i=1; i<=100; i++ )) do if (( $i%2 == 0 )) then continue; else echo -n "$i " fi done echo ------------------------ #!/bin/bash for (( j=1; ; )) do echo -n "$j " let j++ if [ $j -eq 100 ];then break #exit fi done echo echo "end" ------------------------- #!/bin/bash if [ $# -ne 1 ];then echo "Usage: sh $0 filename" exit 1 fi if [ ! -e $1 ];then exit 2 fi 2. 循环实例 --做重复的事 2.1 for 循环语句 do --开始 done --完成 格式: for var in 1 2 3 4 5 do statement done 类似于C语言的方式: for (( var=1 ; var < 6 ; var++ )) --((开始条件;结束条件;变化的条件)) do statement done for (( var=5; var >0 ; var-- )) do statement done 2.1.1 for循环举例 for i in 1 2 3 4 5 do echo -ne "$i\n"--如果不使用-n参数,默认会一个数字打印一行,-e参数代表后面如果使用\n(换行),\t(制表符)等这种字符时会生效,所以这句和echo $i效果一样 done for i in `seq 100` --产生1到100的序列,默认从1开始 do echo -n $i done for i in $(seq 100) --也是产生1到100的序列,这是另一种写法 do echo -n $i done for i in `seq 50 100` --从50到100,50是开始,100是结束 do echo -n $i done echo for i in `seq 1 2 100` --从1开始到100,中间的2为步长 do echo -n $i done echo for i in `seq 100 -2 51` do echo -n "$i " done echo for i in {50..100} do echo -n $i done echo for i in {50..100..2} --步长是在最后 do echo -n $i done echo for i in {100..50..-2} do echo -n $i done echo for i in {100..-50} do echo -n $i done echo for i in {a..z} do echo -n $i done for (( i=50 ;i <101; i+=2 )) do echo -n $i done echo # echo {000..100} # seq -w 1 100 | xargs
计算1到100的和 #!/bin/sh sum=0 for (( i=1; i<=100; i++ )) do sum=$[$sum + $i]; done echo $sum ----------------------------- #!/bin/sh sum=0 for i in {1..100} do sum=$[$sum+$i] done echo $sum 写一个脚本,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里(如果例举整个网段的254个IP花的时间比较长,可以只分类192.168.1.10到192.168.1.30) #!/bin/bash if [ -e /tmp/1.txt -a -e /tmp/2.txt ];then rm /tmp/1.txt rm /tmp/2.txt fi for i in 192.168.1.{1..30} do ping $i -c 2 &> /dev/null if [ $? -eq 0 ];then echo $i >> /tmp/1.txt else echo $i >> /tmp/2.txt fi done echo "ping通的ip是: " cat /tmp/1.txt echo "==============================" echo "ping不通的ip是: " cat /tmp/2.txt
2.2 while 用于不定次数的循环,或死循环 while [条件] do statement done ---------------------- 主要用户不定次数的循环: #!/bin/bash name=0 uid=0 gid=0 # read一次读一行,将一行的内容赋值给line变量,文件有多少行就循环多少次 cat /etc/passwd | while read line do name=`echo $line | cut -d ":" -f1` uid=`echo $line | cut -d ":" -f3` gid=`echo $line | cut -d ":" -f4` echo "$name的uid是$uid,gid是$gid" done ---------------------------- 求1+2+...+100的和 #!/bin/bash i=1 sum=0 while (( i <=100 )) do sum=$[$sum+$i] let i++ done echo $sum 2.2.1 死循环四种: while true --true是真的意思,条件永远成立,一直执行 do statement done while : do statement done for (( ; ; )) --分号不能少,表示空语句 do statement done for ((i=1;;i++)) do statement done ------------------------- #!/bin/bash for (( ; ; )) do clear date "+%Y-%m-%d %H:%M:%S" sleep 1 done 2.3 until 循环 --直到满足条件就退出循环 --使用很少 实例 用until实现打印1到5 #!/bin/bash a=1 until (( $a > 5 )) do echo $a let a++ done echo "========================" i=1 while (( $i <= 5 )) do echo $i let i++ done 3. 随机数 bash默认有一个$RANDOM的变量 使用set |grep RANDOM 查看上一次产生的随机数 echo $RANDOM 产生100内的随机数 echo $[$RANDOM%101] 产生0-1之间的随机数 echo $[$RANDOM%2] 产生1-2之内的随机数 echo $[$RANDOM%2+1] 产生50-100之内的随机数 echo $[$RANDOM%51+50] 产生三位数的随机数 echo $[$RANDOM%900+100] 随机产生100个电话号码:1350755xxxx #!/bin/sh for i in {1..100} do echo 1350755$[$RANDOM%9000+1000] echo 135$[$RANDOM%9000+1000]$[$RANDOM%9000+1000] done 4. 循环嵌套 --循环里面还有循环,了解 for (( )) do for (( )) do statement done done for (( )) do while [condition] do statement done done while [condition] do for (( )) do statement done done while [condition] do while [condition] do statement done done #!/bin/sh for (( i=0; i<5; i++ )) do for (( j=0; j<i; j++ )) do echo -n "* " done echo done * * * * * * * * * * #!/bin/bash for (( i=0; i<5; i++ )) do for (( j =0; j<5 ; j++ )) do echo -n "* " done echo done * * * * * * * * * * * * * * * * * * * * * * * * * 写一个小闹钟的程序 (每秒都显示时间,当到了定时的时间,就循环打印5个*,间隔一秒) --可以替代at服务做一到时间就触发脚本,并且可以精确到秒 #!/bin/bash while true do now=`date +%H:%M:%S` echo $now sleep 1 clear if [ "$1" == "$now" ];then echo "时间到了" /etc/init.d/httpd restart break --在这里是表示打完*后,跳出循环,继续执行循环体后面的代码;如果换成exit则表示直接退出脚本 fi done echo echo 'it is time'
1.用Shell编程,判断一文件是不是字符设备文件,如果是将其拷贝到/root目录下。 #!/bin/bash # 传递一个参数 if [ ! $# -eq 1 ];then echo "请传入一个参数" exit fi # 先判断文件是否存在,文件存在就判断是否是字符设备文件,文件不存在退出程序 if [ -e $1 ];then if [ -c $1 ];then cp -a $1 /root/ if [ $? -eq 0 ];then echo "拷贝完成" else echo "拷贝出错" fi fi else echo "文件不存在" exit fi 2.设计一个shell程序,添加一个新组为class1,然后添加属于这个组的30个用户,用户名的形式为stdxx,其中xx从01到30。 #!/bin/bash groupadd class1 &> /dev/null if [ $? -eq 0 ];then for user in std{01..30} do id $user &> /dev/null # 判断$user是否存在 if [ $? -eq 0 ];then # $user存在 userdel -r $user useradd -G class1 $user else # 不存在 useradd -G class1 $user fi done else echo "class1组已经存在" read -p "你是否要删除已经存在的组class1[y/n]" yn if [ "$yn" = "y" ];then groupdel class1 groupadd class1 for user in std{01..30} do id $user &> /dev/null # 判断$user是否存在 if [ $? -eq 0 ];then # $user存在 userdel -r $user useradd -G class1 $user else # 不存在 useradd -G class1 $user fi done else echo "退出程序" exit fi fi 3.编写shell程序,实现自动删除50个账号的功能。账号名为stud1至stud50。 #!/bin/bash for user in stud{1..50} do id $user &> /dev/null if [ $? -eq 0 ];then userdel -r $user fi done 4.在根目录下创建四个文件m1.txt,m2.txt,m3.txt,m4.txt,用Shell编程,实现自动创建m1,m2,m3,m4四个目录,并将m1.txt ,m2.txt,m3.txt,m4.txt 四个文件分别拷贝到各自相应的目录下 #!/bin/bash touch /m{1..4}.txt for i in {1..4} do mkdir -p /m${i} cp -a /m${i}.txt /m${i} done 5.设计一个Shell程序,在/userdata目录下建立50个目录,即user1~user50,并设置每个目录的权限,其中其他用户的权限为:读;文件所有者的权限为:读、写、执行;文件所有者所在组的权限为:读、执行(rwxr-xr--754) #!/bin/bash for i in user{1..50} do mkdir -p /userdata/$i done chmod 754 /userdata/ -R 6.设计一个shell程序,备份并压缩/etc目录的所有内容,存放在/root/bak目录里,且文件名为如下形式yymmdd_etc,yy为年,mm为月,dd为日。 #!/bin/bash YY=`date +%Y` MM=`date +%m` DD=`date +%d` mkdir -p /root/bak tar zcf /root/bak/${YY}${MM}${DD}_etc.tar.gz /etc/ &> /dev/null 7.gameser这个服务启动命令为./gameser服务,请写一个脚本,当服务宕掉,脚本自动拉起gameser服务。 使用系统自带的软件apache做实验 #!/bin/bash while true do #如何判断一个程序是否在运行? pid=`pidof httpd | cut -d " " -f1` #判断pid变量是否为空 if [ -z $pid ];then # pid为空,服务未启动,将其启动 service httpd start fi sleep 3 done ----------------------- gameser程序: #!/bin/bash while true do #如何判断一个程序是否在运行? pid=`pidof gameser | cut -d " " -f1` #判断pid变量是否为空 if [ -z $pid ];then # pid为空,服务未启动,将其启动 ./gameser fi sleep 3 done