shell脚本02

for 循环语句 循环固定次数
语法结构:
1、列表for循环:用于将一组命令执行已知的次数,下面给出了for循环语句的基本格式:
for variable in {list}
       do
                command 
                command
                 …
        done
  或者
for variable in a b c
       do
              command
              command
       done


2、不带列表for循环:执行时由用户指定参数和参数的个数,下面给出了不带列表的for循环的基本格式:
for variable
       do
             command 
             command
             …
       done


3、类C风格的for循环:一般用于循环次数已知的情况,下面给出了类C风格的for循环的语法格式:
for(( expr1; expr2; expr3 ))
     do
           command
           command
            …
     done




表达式expr1:循环变量赋初值的语句
表达式expr2:决定是否进行循环的表达式,当判断expr2退出状态为0执行do和done之间的循环体,当退出状态为非0时将退出for循环执行done后的命令
表达式expr3:用于改变循环变量的语句


循环示例:
 1119  for ((i=1;i<=5;i++));do echo $i;done
 1120  for ((i=1;i<=5;++i));do echo $i;done
 1121  for i in {1..50};do echo $i;done
 1122  for i in {1..10};do echo $i;done
 1123  for i in 1 2 3 4 5 6 7 8 9 10;do echo $i;done
 1124  for i in `seq 10`;do echo $i;done
 1125  for i in $(seq 10);do echo $i;done
 1127  for i in {1..10..2};do echo $i;done
 1128  for i in {0..10..2};do echo $i;done
 1129  for i in `seq 1 2 10`;do echo $i;done
 1130  for i in `seq 0 2 10`;do echo $i;done
 1131  for ((i=1;i<=10;i+=2));do echo $i;done


demo1:
计算1到100的奇数之和,方法不止一种
方法1:
#!/bin/bash
sum=0
for i in {1..100..2}
  do
echo sum=$[$sum+$i]
         
  done
echo "1到100的奇数之和为:$sum"


方法2:
sum=0
for((i=1;i<=100;i+=2))
 do
let sum=$sum+$i
 done
echo "1到100的奇数之和为:$sum"


方法3:
#!/bin/bash
sum=0
for i in `seq 100`
 do
 [ $[$i%2] -ne 0 ] && sum=$[$sum+$i]
 done
echo "1到100的奇数之和为:$sum"


方法4:
#!/bin/bash
sum=0
for i in `seq 100`
 do
 [ $[$i%2] -eq 0 ] && continue || sum=$[$sum+$i]
 done
echo "1到100的奇数之和为:$sum"




#!/bin/bash
sum=0
for i in `seq 100`
 do
   if [ $[$i%2] -eq 0 ];then
continue
   else
sum=$[$sum+$i]
   fi
 done
echo "1到100的奇数之和为:$sum"




循环控制:
continue:继续。表示循环体内下面的代码不执行,重新开始下一次循环
break:打断。马上停止执行本次循环,执行循环体后面的代码
exit:表示直接跳出程序




demo2:
输入一个正整数,判断是否为质数(素数)
质数:只能被1和它本身整除的数叫质数。
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
思路:
1、如果能被其他数整除就不是质数——>$num%$i 是否等于0
2、如果输入的数是1或者2取模根据上面判断又不符合,所以先排除1和2
3、测试序列从3开始,输入的数是4——>得出结果$num不能和$i相等,并且$num不能小于$i


#!/bin/bash
read -p "输入一个正整数(大于等于1):" num
if [  $num -eq 2 ];then
echo "$num是质数"
      exit
 elif [ $num -eq 1 ];then
        echo "$num不是质数"
        exit 
fi
      
for i in `seq 2 $[$num-1]`  #如果结束序列等于或者大于num变量本身,则变量i总有一次和num相等,所以不能大于等于
do
if [ $[$num%$i] -eq 0 ];then
echo "$num不是质数"
              exit 2
fi
done
echo "$num是质数"


demo3:
批量加5个新用户,以u1到u5命名,并统一加一个新组,组名为class,统一改密码为123
#!/bin/bash
grep ^class$ /etc/group &>/dev/null
test $? -ne 0 && groupadd class
for i in {1..5}
  do
    useradd u$i -G class
    echo 123|passwd --stdin u$i &>/dev/null
  done




#!/bin/bash
groupadd class &>/dev/null
for ((i=1;i<=5;i++))
  do
    useradd u$i -G class
    echo 123|passwd --stdin u$i &>/dev/null
 done




思考:如果事先需要判断class组是否存在,怎么办?
cut -d: -f1 /etc/group |grep -w class 
-w:精确匹配




课堂练习:
1、再次批量新建5个用户stu1~stu5,要求这几个用户的家目录都在/rhome.提示:需要判断该目录是否存在
#!/bin/bash
dir=/rhome
test ! -d $dir && mkdir $dir
或者
[ ! -d $dir ] && mkdir $dir
或者
if [ ! -d $dir ];then
   mkdir $dir
fi


for i in {1..5}
 do 
useradd -d $dir/stu$i stu$i
echo 123|passwd --stdin stu$i
 done


如何再去判断用户是否存在?如果存在就不创建,如果不存在就创建它




2、写一个脚本,局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里(如果例举整个网段的254个IP花的时间比较长,可以只分类10个ip192.168.1.10~20)  这只是一个局域网内机器检查通讯的一个思路。
需求:172.16.13.1~172.16.13.254
#!/bin/bash
for i in {1..254}
 do
echo 172.16.13.$i >> /shell/shell02/ip.txt
 done


for i in `cat /shell/shell02/ip.txt`
  do
    ping -c1 $i &>/dev/null
    [ $? -eq 0 ] && echo $i >> /shell/shell02/ip_ok.txt || echo $i >> /shell/shell02/ip_down.txt
  done


#!/bin/bash
ip=172.16.13.
for i in {1..254}
 do
   ping -c1 $ip$i &>/dev/null
   [ $? -eq 0 ] && echo $i >> /shell/shell02/ip_ok.txt || echo $i >> /shell/shell02/ip_down.txt
 done




until循环  条件为真就退出循环;条件为假就死循环
语法结构:
until expression
do 
         command
         command
         …
done
until循环中expression的退出状态不为0(表达式为假)将循环体一直执行下去,直到退出状态为0(表达式为真)
demo1:用until实现打印1到5
demo2:用until改写批量创建用户


 1198  until false;do echo hello;done
 1199  i=1;until [ $i -gt 5 ];do echo $i;let i++;done


# cat until1.sh 
#!/bin/bash
i=1
until [ $i -gt 5 ]
  do
echo $i
  let i=$i+1
 done




 1210  for ((i=1;i<=10;i+=2));do echo $i;done
 1211  i=1;until (( $i > 10 ));do echo $i;let i+=2;done
 1212  i=1;until [ $i -gt 10 ];do echo $i;let i+=2;done
 1214  sum=0;for ((i=1;i<=10;i+=2));do sum=$[$sum+$i];echo "sum=$sum";done
 1215  sum=0;for ((i=1;i<=10;i+=2));do sum=$[$sum+$i];done;echo "sum=$sum"
 1216  sum=0;i=1;until (( $i > 10 ));do sum=$[$sum+$i];let i+=2;done;echo "sum=$sum"
 1217  sum=0;i=1;until [ $i -gt 10 ];do sum=$[$sum+$i];let i+=2;done;echo "sum=$sum"


#!/bin/bash
i=1
until [ $i -gt 5 ]
  do
useradd uu$i
echo 123|passwd --stdin uu$i &>/dev/null
  let i++
  done






while循环 满足条件(真)就进入死循环;条件为假就退出循环
语法结构:
 while expression   只要条件满足就一直循环
  do
     command
    command
 done




计算1-50的偶数之和
 1230  sum=0;i=2;while [ $i -le 50 ];do sum=$[$sum+$i];let i+=2;done
 1231  sum=0;i=2;while [ $i -le 50 ];do sum=$[$sum+$i];let i+=2;done;echo "sum=$sum"
 1232  sum=0;i=1;while [ $i -le 50 ];do sum=$[$sum+$i];let i+=2;done;echo "sum=$sum"




demo1:打印1-5数字
demo2:
写一个30秒同步一次时间同步服务器172.16.13.250的脚本,如果同步失败,则进行邮件报警,每次失败都报警;同步成功,也进行邮件通知,但是成功100次才通知一次。


rdate -s 172.16.13.250
ntpdate 172.16.13.250
#!/bin/bash
ip=172.16.13.250
count=0
while true
do
rdate -s $ip &>/dev/null
[ $? -ne 0 ] && echo "系统时间同步失败,请注意" |mail -s "系统时间同步检查" root ||let count++
[ $count -eq 100 ] && echo "系统时间同步成功100次" |mail -s "系统时间同步检查" root && count=0
sleep 30
done






#!/bin/bash
count=0
while true
do
  ntpdate 192.168.1.10 &> /dev/null
if [ $? -ne 0 ];then
        echo "ntpdate failed" |mail -s "time sync problem" mail01
else
        let count++  或者let count=$count++
        if [ $count -eq 100 ];then  
        echo "ntpdate successd" |mail -s "time sync ok" mail01
        count=0
        fi
        或者
        [ $count -eq 100 ] && echo "ntpdate successd" |mail -s "time sysnc ok" root && count=0
        或者
        [ $[$count%100] -eq 0 ] && echo "ntpdate successd" |mail -s "time sysnc ok" root 
fi
sleep 30
done


注意:因为是一个死循环,所以放到后台执行。


总结:
用至少三种方法打印1~5和5~1
打印1~5:
for i in {1..5};do echo $i;done
for i in `seq 5`;do echo $i;done
for ((i=1;i<=5;i++));do echo $i;done
while和until


打印5~1:
# for i in {5..1};do echo $i;done
# for i in `seq 5 -1 1`;do echo $i;done
# for ((i=5;i>=1;i--));do echo $i;done
while和until




 1262  for ((i=1;i<=5;i++));do echo $i;done
 1263  for ((i=5;i>=1;i--));do echo $i;donw
 1264  for ((i=5;i>=1;i--));do echo $i;done
 1265  i=1;until [ $i -gt 5 ];do echo $i;let i++;done
 1266  i=5;until (( $i < 1 ));do echo $i;let i--;done
 1267  i=1;until (( $i > 5 ));do echo $[6-$i];let i++;done
 1268  i=1;while [ $i -le 5 ];do echo $i;let i++;done
 1269  i=1;while (( $i <= 5 ));do echo $((6-$i));let i++;done




随机数:
bash默认有一个$RANDOM的变量 默认是0~32767。使用set |grep RANDOM 查看上一次产生的随机数


echo $RANDOM


产生0~1之间的随机数
echo $[$RANDOM%2]


产生0~2之间的随机数
echo $[$RANDOM%3]


产生0~3之间的随机数
echo $[$RANDOM%4]
。。。。
产生0~9内的随机数
echo $[$RANDOM%10]


产生0~100内的随机数
echo $[$RANDOM%101]




产生50-100之内的随机数
echo $[$RANDOM%51+50]


产生三位数的随机数
echo $[$RANDOM%900+100]




demo1:
写一个脚本,产生一个phonenum.txt文件,随机产生以139开头的手机号1000个,每个一行。
方法一:
for i in `seq 1000`
do
n1=$[$RANDOM%10]
n2=$[$RANDOM%10]
n3=$[$RANDOM%10]
n4=$[$RANDOM%10]
n5=$[$RANDOM%10]
n6=$[$RANDOM%10]
n7=$[$RANDOM%10]
n8=$[$RANDOM%10]
echo "139$n1$n2$n3$n4$n5$n6$n7$n8" >> phonenum.txt
done


方法二:
count=0
while true
do
n1=$[$RANDOM%10]
n2=$[$RANDOM%10]
n3=$[$RANDOM%10]
n4=$[$RANDOM%10]
n5=$[$RANDOM%10]
n6=$[$RANDOM%10]
n7=$[$RANDOM%10]
n8=$[$RANDOM%10]
echo "139$n1$n2$n3$n4$n5$n6$n7$n8" >> phonenum.txt && let count++
if [ $count -eq 1000 ];then
break
fi

done




demo2:再写一个脚本,在上面的1000个手机号里抽奖5个幸运观众,显示出这5个幸运观众。但只显示头3个数和尾号的4个数,中间的都用*代替
#第一种抽法,每个人不限次数
#!/bin/bash
file=/shell/shell02/phonenum.txt
for i in {1..5}
do
line=`wc -l $file |cut -d' ' -f1`
luck=$[$RANDOM%$[$line+1]]
lucknum=`head -$luck $file|tail -1` 
echo "幸运观众是:139****${lucknum:7:4}"
done


#第二种抽法,每个人就只有一次机会
#!/bin/bash
file=/shell/shell02/phonenum.txt
for i in {1..5}
do
line=`wc -l $file |cut -d' ' -f1`
luck=$[$RANDOM%$[$line+1]]
lucknum=`head -$luck $file|tail -1`
sed -i "/$lucknum/d" $file
echo "幸运观众是:139****${lucknum:7:4}"
done




嵌套循环
一个循环体内又包含另一个完整的循环结构,称为循环的嵌套。在外部循环的每次执行过程中都会触发内部循环,直至内部完成一次循环,才接着执行下一次的外部循环。for循环、while循环和until循环可以相互嵌套。


demo1:打印如下图案
1
12
123
1234
12345


#!/bin/bash
for ((y=1;y<=5;y++))
do
for ((x=1;x<=$y;x++))
do
echo -n $x
done
echo
done


#!/bin/bash
for ((y=1;y<=5;y++))
do
x=1
while [ $x -le $y ]
do
echo -n $x
let x++
done
echo
done


#!/bin/bash
y=1
until (( $y > 5 ))
do
x=1
while (( $x <=$y ))
do
echo -n $x
let x++
done
echo
let y++
done






demo2:打印如下图案


5
54
543
5432
54321




for ((y=5;y>=1;y--))
do
x=5
until (( $x < $y ))
do
echo -n $x
let x--
done
echo
done








课堂练习:打印九九乘法表(三种方法)


1*1=1


1*2=2   2*2=4


1*3=3   2*3=6   3*3=9


1*4=4   2*4=8   3*4=12  4*4=16


1*5=5   2*5=10  3*5=15  4*5=20  5*5=25


1*6=6   2*6=12  3*6=18  4*6=24  5*6=30  6*6=36


1*7=7   2*7=14  3*7=21  4*7=28  5*7=35  6*7=42  7*7=49


1*8=8   2*8=16  3*8=24  4*8=32  5*8=40  6*8=48  7*8=56  8*8=64


1*9=9   2*9=18  3*9=27  4*9=36  5*9=45  6*9=54  7*9=63  8*9=72  9*9=81




方法一(for循环):
方法二:while循环
方法三:until循环




练习
         x
        xxx
       xxxxx
      xxxxxxx
     xxxxxxxxx
   
#!/bin/sh
i=1
while [ $i -le 5 ] ; do
j=1
while [ $j -le $((5-$i)) ] ; do
echo -n ' '
j=$(($j+1))
done


j=1
while [ $j -le $((2*$i-1)) ] ; do
echo -n x
j=$(($j+1))
done
echo
i=$(($i+1))
done
exit 0


作业:
1、将/etc/passwd里的用户名分类,分为管理员用户,系统用户,普通用户。
#!/bin/bash
for i in `cut -d: -f1,3 /etc/passwd`
do
uid=`echo $i|cut -d: -f2`
name=`echo $i|cut -d: -f1`
[ $uid -eq 0 ] && echo $name >> /tmp/管理员
[ $uid -gt 0 -a $uid -lt 500 -o $uid -eq 65534 ] && echo $name >> /tmp/系统用户
[ $uid -ge 500 -a $uid -ne 65534 ] && echo $name >>/tmp/普通用户
done


参考:
作业1:
1、将/etc/passwd里的用户名分类,分为管理员用户,系统用户,普通用户。
答:
写法1
#!bin/bash
for i in `cat /etc/passwd|cut -d: -f1`
do
[ $(id $i -u) -eq 0 ] && admin=$i
[ $(id $i -u) -gt 0   -a $(id $i -u) -lt 500   ] && sys=$sys$i" "
[ $(id $i -u) -ge 500 -a $(id $i -u) -lt 65535 ] && custom=$custom$i" "
done
echo -e "管理员用户:\n $admin \n系统用户:\n ${sys}\n普通用户:\n ${custom}"
--------------------------------------------------------
写法2
#!bin/bash
for i in `cat /etc/passwd|cut -d: -f1,3`
do
[ ${i#*:} -eq 0 ] && admin=${i%:*}
[ ${i#*:} -gt 0   -a ${i#*:} -lt 500   ] && sys=$sys${i%:*}" "
[ ${i#*:} -ge 500 -a ${i#*:} -lt 65535 ] && custom=$custom${i%:*}" "
done
echo -e "管理员用户:\n $admin \n系统用户:\n ${sys}\n普通用户:\n ${custom}"
--------------------------------------------------------
写法3
#!bin/bash
for i in `cat /etc/passwd|cut -d: -f1,3`
do
x=`echo $i|cut -d: -f2`
y=`echo $i|cut -d: -f1`
[ $x -eq 0 ] && admin=$y
[ $x -gt 0 -a $x -lt 500 ] && sys=$sys$y" "
[ $x -ge 500 -a $x -lt 65535 ] && custom=$custom$y" "
done
echo -e "管理员用户:\n $admin \n系统用户:\n ${sys}\n普通用户:\n ${custom}"
------------------------------------------------------


2、写一个倒计时脚本,要求显示离2017年10月1日(国庆节)的凌晨0点,还有多少天,多少时,多少分,多少秒。
#!/bin/bash
guoqing=`date +%s -d '2017-10-01 00:00:00'`
while true
do
now=`date +%s`
if [ $[$guoqing-$now] -eq 0 ];then
break
fi
day=$[$[$guoqing-$now]/86400]
hour=$[$[$guoqing-$now]%86400/3600]
min=$[$[$guoqing-$now]%3600/60]
sec=$[$[$guoqing-$now]%60]
echo "距离国庆节还有:$day天:$hour小时:$min分钟:$sec秒!"
sleep 1
clear

done
echo "国庆节快乐!!!"


3、写一个脚本把一个目录内的所有空文件都删除,最后输出删除的文件的个数。
#!/bin/bash
count=0
read -p "请输入需要删除文件的路径:" path
for i in `find $path -type f`
 do
[ ! -s $i ] && rm -f $i && count++
 done
echo "总共删除了$count个空白文件!"


4、写一个自动搭建apache服务的脚本
方法1:
函数实现循环输入(不输入ip地址、主机名、数据根目录一直提示输入)


需求:输入一个域名 ——>this is test.cc test page
IP:10.1.1.1
hostname:
root_dir:


#!/bin/bash
fun_hello(){
in_var=''
while [ -z $in_var ]
do
in_put=$1
read -p "$in_put" in_var
done
echo $in_var
}


ip=`fun_hello "请输入你的IP地址:"`
hostname=`fun_hello "请输入你的域名:"`
root_dir=`fun_hello "请输入你的数据根目录:"`


#主机名和ip地址绑定到hosts文件里
cat >>/etc/hosts<<end
$ip $hostname
end


#创建相应的数据根目录和首页文件
[ ! -d $root_dir ] && mkdir -p $root_dir || chown -R apache. $root_dir
echo "this is test.cc test page " >$root_dir/index.html


#发布虚拟主机
cat >> /etc/httpd/conf/httpd.conf <<end
NameVirtualHost *:80
<VirtualHost *:80>
    ServerAdmin webmaster@dummy-host.example.com
    DocumentRoot $root_dir
    ServerName $hostname
    ErrorLog logs/dummy-host.example.com-error_log
    CustomLog logs/dummy-host.example.com-access_log common
</VirtualHost>
end


#启动服务
service httpd restart &>/dev/null
#测试验证


方法2:
while或until循环



















  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值