Bash shell学习笔记(三)

课程目标

  • 掌握for循环语句的基本语法结构
  • 掌握while和until循环语句的基本语法结构
  • 能使用RANDOM变量产生随机数
  • 理解嵌套循环

易混符号小结

符号说明
$( )执行符
`` 反撇号,不是单引号执行符
$[ ]运算符
$(( ))运算符
${ }获取变量并可以做截取
[ ]判断条件
[[ ]]判断条件,里面可以使用正则

循环语句

生活中的循环

在这里插入图片描述

运维维护中经常会出现重复多次执行的工作,如批量建用户,批量删除文件等。利用shell里的循环语句可以很好地帮我们解决问题。

1. for循环

特点: 多用于已知次数的循环(定循环),比如循环100次,循环一个目录下的文件,这些都是有一定次数的。

for循环语法结构

for variable in 1 2 3 4 5
do
	command
	command
	......
done

for(( expr1;expr2;expr3 ))				# 类C风格的for循环
do
	command
	command
	......
done

expr1:定义变量并赋初值
expr2:决定是否进行循环(条件)
expr3:决定循环变量如何改变,决定循环什么时候退出

for结构循环数字或字母

#!/bin/bash

for i in 1 2 3 4 5
do
        echo $i
done

其它示例:

# for i in `seq 10`;do echo $i;done
# for i in $(seq 10);do echo $i;done
# for i in `seq 10 -2 1`;do echo $i;done

# for i in {1..10};do echo $i;done
# for i in {0..10..2};do echo $i;done			# 大括号中第3个数字2为一步的长度
# for i in {10..1};do echo $i;done
# for i in {10..1..-2};do echo $i;done

# for ((i=1;i<=5;i++));do echo $i;done
# for ((i=1;i<=10;i+=2));do echo $i;done
# for ((i=10;i>=1;i-=2));do echo $i;done

# for i in {a..z}; do echo $i; done

示例: 用循环实现计算1+2+3的和

#!/bin/bash

sum=0

i=1
sum=$[$sum+$i]
# sum结果为0+1=1

i=2
sum=$[$sum+$i]
# sum结果为1+2=3

i=3
sum=$[$sum+$i]
# sum结果为3+3=6

sum=0
for i in {1..3}
do
        sum=$[$sum+$i]
done
echo $sum

示例: 计算1到100的奇数之和

思路:
1. 定义一个变量来保存奇数的和	sum=0
2. 找出1-100的奇数,保存到另一个变量里  i
3. 从1-100中一个一个地找出奇数后,再相加,然后将和赋值给sum变量
4. 循环完毕后,将sum的值打印出来
#!/bin/bash

sum=0
for i in {1..100..2}
do
        sum=$[$sum+$i]
done
echo $sum

循环控制语句

循环体: do…done之间的内容

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

示例: 改写计算1到100的奇数之和

continue来改写
sum=0
for i in {1..100}
do
        if [ $[$i%2] -eq 0 ];then
                continue
        fi
        sum=$[$sum+$i]
done
echo $sum

示例: 批量加10个用户, 以student1到student10命名,并统一加一个新组,组名为class,统一改密码为123

#!/bin/bash

groupadd class

# 思路如下
#useradd student1 -G class
#echo 123 | passwd --stdin student1 &> /dev/null


#useradd student2 -G class
#echo 123 | passwd --stdin student2 &> /dev/null


#useradd student3 -G class
#echo 123 | passwd --stdin student3 &> /dev/null
#......

# 把上述思路做成循环
for i in {1..10}
do
        useradd student$i -G class
        echo 123 | passwd --stdin student$i &> /dev/null
done

示例: 批量删除上例建立的10个用户(包括把用户的家目录和邮件目录给删除干净),并删除class组

#!/bin/bash

for i in student{1..10}
do
        userdel -r $i &> /dev/null
done
groupdel class
echo "删除成功"

for结构循环linux文件

比较下列两段的区别:

for file in /etc/*
do
	echo $file
done

for file in $(find /etc)
do
	echo $file
done

示例: 找出/usr/share/doc目录下所有文件名为index.html的文件,把他们拷到/tmp/index目录下,文件名按找到的先后更改,第一个找到的为index.html.1,第二个找到的为index.html.2。。。。以此类推

#!/bin/bash

rm -rf /tmp/index/
mkdir /tmp/index/ -p

count=1
for file in $(find /usr/share/doc/ -name "index.html")
do
	cp $file /tmp/index/index.html.$count
	count=$[$count+1]				# 或者let count++
done

练习: read输入一个目录,查找此目录下所有的死链接文件

#!/bin/bash

read -p "输入一个目录:" dir

if [ ! -d $dir ];then
        echo "你输入的不是目录"
        exit
fi

for file in $(find $dir -type l)
do
        if [ ! -e $file ];then
                echo "$file是死链接文件"
        fi
done

2. while循环

特点: 条件为真就进入循环;条件为假就退出循环.多用于不定次数的循环

for循环常用于定循环,while循环常用于不定循环,很多场景两个都可以用

如:

6点-18点,每个小时整点循环(定了次数,每天都会有6点-18点)

当有太阳,每个小时整点循环(不定次数,天气和季节都会影响是否有太阳)

while循环语法结构

while 条件
do
      条件满足时候:执行动作一
	  条件满足时候:执行动作二
      ......
done

示例: 用for循环与while循环做比较打印1-5

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

i=1
while [ $i -le 5 ]
do
	echo $i
	let i++
done

死循环

死循环就是一直循环,除非使用循环控制语句跳出

while true			条件永远为true,所以会一直循环下去
do
	command
done
其它的死循环写法,不要去记,会上面一种即可
while :
do
	command
done

for (( ;1; ))
do
	command
done

for ((i=1;;i++))
do
	command
done

示例: 每隔1秒钟打印累加的数字

#!/bin/bash

a=1
while true
do
        echo $a
        let a++
        sleep 1						# 等待1秒
done

示例:

写一个30秒同步一次时间,同步服务器为10.1.1.12的脚本,如果同步失败,则使用logger记录到/var/log/messages里,每次失败都记录;同步成功,也进行日志记录,但是成功100次才记录一次。

准备工作:

在这里插入图片描述

在时间服务器上操作

# yum install xinetd  -y

# vim /etc/xinetd.d/time-stream
6       disable         = no				把yes改为no

# /etc/init.d/xinetd restart

# netstat -ntlup |grep :37
tcp        0      0 :::37         :::*         LISTEN      6801/xinetd 

在客户端上写脚本同步

分析:

  • 不能使用crond来实现(因为crond最少时间间隔单位为1分钟)
  • 每个30s同步一次时间,使用死循环,使用sleep 30实现等待30秒
  • 同步失败记录日志
    • 在do…done循环体之间加if…else…(判断同步失败还是成功)
  • 同步成功100次发送邮件
    • 统计成功次数——>count=0——>成功1次加+1
# yum install rdate -y

#!/bin/bash

count=0
while true
do
	rdate -s 10.1.1.12 &> /dev/null
	if [ $? -ne 0 ];then
		logger -t "rdate时间同步" "同步失败"
	else
		count=$[$count+1]							# 每成功一次计数加1
		if [ $count -eq 100 ];then
		 	logger -t "rdate时间同步" "同步成功"
			count=0									# 当累计100次记录成功日志后,清零计数
		fi
	fi	 
	sleep 30										# sleep等待30秒
done

3. until循环(了解)

特点: 直到满足条件就退出循环

until 条件				# 直到满足条件就退出循环
do
	command
	command
	......
done

比较for与until打印1-5

a=1
until [ $a -gt 5 ]	  			for ((a=1;a<6;a++))
do								do
        echo $a						echo $a
        let a++					done
done

建议: until循环结构看得懂就好。因为for与while就完全可以胜任所有的循环,并且后面学习python,python就只有for与while.

随机数

bash默认有一个$RANDOM的变量, 默认范围是0~32767.

使用set |grep RANDOM查看上一次产生的随机数

# echo $RANDOM
19862
# set |grep RANDOM
RANDOM=19862

产生0~1之间的随机数

# echo $[$RANDOM%2]

产生0~2之间的随机数

# echo $[$RANDOM%3]

产生1-2之内的随机数

# echo $[$RANDOM%2+1]

产生50-100之内的随机数

# echo $[$RANDOM%51+50]

产生三位数的随机数

# echo $[$RANDOM%900+100]

示例: 写一个猜数字的小游戏

#!/bin/bash

echo "猜一个1-100的整数,猜对砸蛋:" 

num=$[$RANDOM%100+1]

while true
do
	read -p "请猜:" gnum
    if [ $gnum -gt $num ];then
		echo "大了"
	elif [ $gnum -lt $num ];then
		echo "小了"
	else	
		echo "对了"
		break
	fi
done

echo "砸蛋"

嵌套循环

一个循环体内又包含另一个完整的循环结构,称为循环的嵌套。

在外部循环的每次执行过程中都会触发内部循环,直至内部完成一次循环,才接着执行下一次的外部循环。

for循环、while循环和until循环可以相互嵌套。

for i in {a..c}
do
        for j in {1..3}
        do
                echo $i$j
        done
done

示例: 打印出如下结果

*
**
***
****
*****
******
回顾echo命令:
echo默认打印会换行
echo -n打印不换行
echo -e会让/n为换行号,\t为制表符(tab键)

# echo -e "你\n好\t吗"
你
好      吗
#!/bin/bash

for i in $(seq 5)					# 循环5行
do
        for j in $(seq $i)			# 每行循环次数和行数保持一致
        do
                echo -n "*"
        done
        echo
done

示例: 打印出如下结果

1
12
123
1234
12345
#!/bin/bash

for i in $(seq 5)
do
       	for j in $(seq $i)
        do
                echo -n $j
        done
        echo
done

课后作业

1, 将/etc/passwd里的用户名分类,分为管理员用户,系统用户,普通用户

#!/bin/bash

rm -rf /tmp/root_user
rm -rf /tmp/system_user
rm -rf /tmp/normal_user

cat /etc/passwd |while read line
do
        user=$(echo $line |cut -d: -f1)
        uid=$(echo $line |cut -d: -f3)
        if [ $uid -eq 0 ];then
                echo "$user" >> /tmp/root_user
        elif [ $uid -ge 1 -a $uid -le 499 -o $uid -eq 65535 ];then
                echo "$user" >> /tmp/system_user
        else
                echo "$user" >> /tmp/normal_user
        fi
done

echo "管理员用户有:"
cat /tmp/root_user
echo
echo "系统用户有:"
cat /tmp/system_user
echo
echo "普通用户有:"
cat /tmp/normal_user

此例后面学习awk后会有更简单的方法

2, 写一个脚本把一个目录内的所有空文件都删除,最后输出删除的文件的个数

方法一:
read -p "输入一个你要删除空文件的目录:" dir

a=0
for i in `find $dir -type f`
do
	[ ! -s $i ] && rm -rf $i && let a++
done

echo "删除的个数为:" "$a"	


方法二:
#!/bin/bash

read -p "输入一个你要删除空文件的目录:" dir

if [ ! -d $dir ];then
        echo "不存在或不是目录,重试"
        exit 0
fi

a=0
for i in `find $dir -size 0 -type f`
do
        rm -rf $i
        let a++
done
echo $a




3, 建立a1, a2, a3, a4, a5, b1, b2, b3, b4, b5。。。。。。。以此类推,一直到e1,e2, e3, e4, e5一共25个用户, 每个用户密码为随机三位数字(100-999), 并将用户名与密码保存到/root/.passwd文件中


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七十一阿哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值