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