1.for循环结构
1.1 for循环结构语法
语法:
for 变量名 in 变量取值列表
do
指令…
done
提示:在此结构中“in 变量取值列表”可省略,省略时相当于in “$@”,也就是使用for i 就相当于for i in “$@”。
说明:在for循环语句中,for关键字后面会有一个"变量名",变量名依次获取in关键字后面的变量取值列表的内容(以空格分隔),每次仅取一个,然后进入循环执行循环中的所有指令,当执行到done时结束本次循环。之后变量在获取变量列表里的下一个变量值。继续执行循环内的命令,当执行到done是结束返回,以此类推直到取完变量列表里的最后一个值进入循环到done结束。
1.2 C语言型for循环结构
语法:
for((exp1; exp2; exp3))
do
指令…
done
说明:for关键字后的括号内是三个表达式,第一个是变量初始化(例如:i=0),第二个是变量的取值范围(例如:i<100),第三个为变量的自增或自减(例如i++)。当第一个表达式的初始化的值符合第二个变量的范围时,就进入循环执行;当条件不满足时就退出循环。
for循环执行流程对应逻辑图如下图所示:
范例:while循环和for循环的对比
先看一下while循环语句
[root@shellbiancheng jiaobenlianxi]# cat while4.sh
#!/bin/bash
i=1
while((i<=10))
do
echo $i
((i++))
done
下面是for循环语句
[root@shellbiancheng jiaobenlianxi]# cat for1.sh
#!/bin/bash
for((i=1;i<=10;i++))
do
echo $i
done
说明:
(1)程序持续运行多用while,包括守护进程。
(2)有限次循环多用for,则多用for,实际工作中for运用的机会更多。
学习记忆的方法:
for 男人 in 所有男人
do
if [ 有房 ] && [ 有车 ] && [ 存款 ] && [ 会做家务 ] && [ 帅气 ] && [ 体贴 ] && [ 逛街买东西 ];then
echo “女孩喜欢这样的男人”
else
rm –f $男人
fi
done
1.3 for循环基础案例
1.3.1 案例1:直接列出变量列表所有元素,打印1,2,3,4,5
方法1:
[root@shellbiancheng jiaobenlianxi]# cat for3.sh
for n in 1 2 3 4 5
do
echo $n
done
方法2:使用大括号的方法
[root@shellbiancheng jiaobenlianxi]# cat for4.sh
for n in {1..10}
do
echo 192.168.1.$n
done
方法3:使用seq生成随机数的方法
[root@shellbiancheng jiaobenlianxi]# cat for5.sh
for n in `seq 5 -1 1` 5是起始数字,-1表示每次减1,1是结束数字
do
echo $n
done
1.3.2 案例2:获取当前目录的文件名
[root@shellbiancheng jiaobenlianxi]# cat for5.sh
for n in `ls`
do
echo $n
done
1.3.3 案例3:随机数生成文件
批量生成文件,文件名随机md5处理后,选八位。
[root@shellbiancheng jiaobenlianxi]# cat suijiwnjian.sh
for((i=1;i<=10;i++))
do
mkdir -p ./test
touch ./test/` echo $RANDOM|md5sum|cut -c 1-8`_finished.html
done
[root@shellbiancheng jiaobenlianxi]# ls test/
0ac2453a_finished.html 8b90c52b_finished.html c4eb22c9_finished.html
2c1f5e87_finished.html a22717d3_finished.html db258218_finished.html
6d6bc69f_finished.html a4aca3b0_finished.html
6d7c516a_finished.html c21f3d55_finished.html
1.3.4 案例4:批量修改文件名
将上面生成的10个以.html结尾的文件修改成以.jpg结尾。并且把finished去掉。
方法一:
[root@shellbiancheng jiaobenlianxi]# cat piliangxiugai1.sh
for f in `ls test/*.html`
do
mv $f `echo $f|sed 's#_finished.html#.jpg#g'`
done
[root@shellbiancheng jiaobenlianxi]# ls test/
0ac2453a.jpg 6d6bc69f.jpg 8b90c52b.jpg a4aca3b0.jpg c4eb22c9.jpg
2c1f5e87.jpg 6d7c516a.jpg a22717d3.jpg c21f3d55.jpg db258218.jpg
方法二:for循环加变量部分截取的方法
[root@shellbiancheng jiaobenlianxi]# cat piliangxiugai3.sh
for file in `ls test/*.html`
do
/bin/mv $file "${file%_finished*}.jpg"
done
方法三:ls结合awk实现
[root@shellbiancheng test]# ls
0513d6f0_finished.html 6ab3573c_finished.html 8abfa660_finished.html
1a9335f3_finished.html 70018e1c_finished.html bb6763ab_finished.html
559d16bc_finished.html 74e206b5_finished.html
58fc15d7_finished.html 7878f84a_finished.html
[root@shellbiancheng test]# ls |awk -F '[_]' '{print "mv " $0,$1".jpg"}'|bash
[root@shellbiancheng test]# ls
0513d6f0.jpg 559d16bc.jpg 6ab3573c.jpg 74e206b5.jpg 8abfa660.jpg
1a9335f3.jpg 58fc15d7.jpg 70018e1c.jpg 7878f84a.jpg bb6763ab.jpg
方法四:通过rename实现
[root@shellbiancheng test]# ls
16d72ca3_finished.html 673c62da_finished.html b9328787_finished.html
37690b31_finished.html 72ebc17d_finished.html e37aeed5_finished.html
37e66161_finished.html a5050e54_finished.html
4efe1f4c_finished.html b2553039_finished.html
[root@shellbiancheng test]# rename "_finished.html" ".jpg" *
[root@shellbiancheng test]# ls
16d72ca3.jpg 37e66161.jpg 673c62da.jpg a5050e54.jpg b9328787.jpg
37690b31.jpg 4efe1f4c.jpg 72ebc17d.jpg b2553039.jpg e37aeed5.jpg
1.3.5 案例5:
实战案例:开发脚本实现仅设置sshd crond rsyslog network 开机自启动
[root@shellbiancheng jiaobenlianxi]# cat chkconfigoff.sh
LANG=en
chkconfig --list|grep 3:on|awk '{print $1}' >b.log
for name in `chkconfig --list|grep 3:on|awk '{print $1}'|egrep -v "sshd|crond|rsyslog|network"`
do
chkconfig $name off
done
[root@shellbiancheng jiaobenlianxi]# cat chkconfigon.sh
LANG=en
for name in `cat b.log`
do
chkconfig $name on
done
1.3.6 案例6:用for循环实现1-100之和
方法一:
[root@shellbiancheng jiaobenlianxi]# cat for1-100.sh
for((i=1;i<=100;i++))
do
let sum+=i
done
echo $sum
[root@shellbiancheng jiaobenlianxi]# sh for1-100.sh
5050
方法二:
[root@shellbiancheng jiaobenlianxi]# cat for1-1000.sh
for n in `seq 100`
do
((sum+=n))
done
echo $sum
方法三:
[root@shellbiancheng jiaobenlianxi]# cat for1-100_3.sh
for n in `seq 100`
do
a="$(($n*($n+1)/2))"
done
echo $a
1.3.7 案例7:实现mysql分库备份
备份数据库的命令为:mysqldump -uroot -p123456 -S /data/3307/mysql.sock -B linzhongniao|gzip
>/server/backup/linzhongniao_$(date +%F).sql.gz
脚本如下:
[root@mysql ~]# cat mysqlfenkubeifen.sh
#!/bin/bash
export PATH="/usr/local/mysql/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin"
DBPATH="/server/backup"
MYUSER="root"
MYPASS="123456"
SOCKET="/data/3307/mysql.sock"
MYCMD="mysql -u$MYUSER -P$MYPASS -S $SOCKET"
MYDUMP="mysqldump -u$MYUSER -p$MYPASS -S $SOCKET -B"
[ -d "$DBPATH" ] || mkdir -p $DBPATH
for dbname in `mysql -u$MYUSER -p$MYPASS -S $SOCKET -e "show databases;"|sed '1d'|egrep -v "mysql|schema"`
do
$MYDUMP $dbname|gzip >$DBPATH/${dbname}_$(date +%F).sql.gz
done
执行结果如下:
[root@mysql ~]# ll /server/backup/
总用量 20
-rw-r--r--. 1 root root 512 10月 4 19:32 dfhjdhf_2018-10-04.sql.gz
-rw-r--r--. 1 root root 822 10月 4 19:32 linzhongniao_2018-10-04.sql.gz
-rw-r--r--. 1 root root 507 10月 4 19:32 nn_2018-10-04.sql.gz
-rw-r--r--. 1 root root 704 10月 4 19:32 school_2018-10-04.sql.gz
-rw-r--r--. 1 root root 509 10月 4 19:32 test_2018-10-04.sql.gz
1.3.8 案例8:利用for循环批量建库
[root@mysql jiaobenlianxi]# cat piliangjianku.sh
#!/bin/bash
export PATH="/usr/local/mysql/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin"
MYUSER="root"
MYPASS="123456"
SOCKET="/data/3307/mysql.sock"
MYCMD="mysql -u$MYUSER -p$MYPASS -S $SOCKET"
RETVAL=0
for dbname in `cat ./dbname.txt`
do
$MYCMD -e "use $dbname;" &>/dev/null
if [ $? -ne $RETVAL ];then
$MYCMD -e "create database $dbname"
else
echo "$dbname" >>./dbnamed.txt
fi
done
1.3.9 案例9:批量创建系统账号并设置密码
[root@mysql jiaobenlianxi]# cat user.sh
#!/bin/bash
#author=linzhongniao
#date:2018-10-04
#mail:[email protected]
#function:Batch create users and set password tests.
#version: 1.1
. /etc/init.d/functions
export PATH="/usr/local/mysql/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin"
RETVAL=0
passfile="./user.log"
PASS="/etc/passwd"
[ -f "$passfile" ]|| touch $passfile
for user in `cat ./user.txt`
do
cat /etc/passwd|grep "$user"&>/dev/null
if [ $? -ne $RETVAL -a -w "$PASS" ];then
passwd="`echo "test$RANDOM"|md5sum|cut -c1-4`"
useradd $user &>/dev/null && echo "$user:$passwd">>$passfile
action "$user is OK." /bin/true
else
action "$user is fail.The user has been created" /bin/false
fi
done
echo "------------------"
chpasswd < $passfile #这个地方很关键读取密码文件对密码进行设置必须是user:passwd这种格式
cat $passfile
2.linux系统产生随机数的方法
方法一:用系统环境变量RANDOM来实现,示例代码如下:
[root@shellbiancheng ~]# echo $RANDOM
11100
[root@shellbiancheng ~]# echo $RANDOM
24323
[root@shellbiancheng ~]# echo "linzhongniao$RANDOM"|md5sum|cut -c1-4
6e9b
RANDOM的随机数范围为0-32767,务必记住,因此加密行不太好;可以通过在输出的随机数前面增加加密字符串的方式来解决,最够用md5sum加密取出想要的部分,这样就不能根据随机数结果猜出具体结果了。
方法二:使用expect附带的mkpasswd生成随机数
mkpasswd命令:mkpasswd——生成新的密码,可选地将其应用于用户;它依赖于数据包expect,因此必须通过“yum install expect -y”先安装该数据包。
相关参数说明:
-l(小写的L)(The -l flag defines the length of the password. The default is 9.) 指定密码的长度,默认长度是9。
-d (The -d flag defines the minimum number of digits that must be in the password. The default is 2.)指定密码中数字的长度默认长度是2。
-c (The -c flag defines the minimum number of lowercase alphabetic charac-ters that must be in the password. The default is 2.)指定密码中小写字母的数量,默认数量是2.
-C(The -C flag defines the minimum number of uppercase alphabetic charac-ters that must be in the password. The default is 2.)指定密码中大写字母的数量,默认数量是2.
-s(The -s flag defines the minimum number of special characters that mustbe in the password. The default is 1.)指定密码中特殊符号的数量,默认是1.
示例代码如下:
[root@shellbiancheng ~]# mkpasswd -l 9 -d 2 -c 3 -C 3 -s 1
Z7vOlf|G8
[root@shellbiancheng ~]# mkpasswd -l 9 -d 2 -c 3 -C 3 -s 1|md5sum|cut -c1-4
242a
3.select循环语句
select循环语句的主要作用可能就是创建菜单相当于用cat方法生成菜单,在执行带select循环语句的脚本时输出会按照数字顺序的列表显示一个菜单项,并显示提示符(默认是#?),同时等待用户输入进行选择。
语法结构如下:
select 变量名 in 菜单取值列表
do
指令....
done
select循环结构执行流程逻辑图如下图所示:
与for循环不同的是,select循环执行后会出现菜单项供用户选择(不会自动循环所有变量列表),用户只能输入菜单项前面的数字序号,每输入一次对应的数字序号就会执行一次循环,直到变量后面对应列表取完为止。
3.1 select循环语句案例
案例一:用select循环打印简单菜单项
方法1:
[root@shellbiancheng jiaobenlianxi]# cat select.sh
#!/bin/bash
select name in linzhongniao zhangsan lisi xiangli
do
echo $name
done
执行结果如下:
[root@shellbiancheng jiaobenlianxi]# sh select.sh
1) linzhongniao
2) zhangsan
3) lisi
4) xiangli
#? 1 默认提示符是#?,后面会换掉
linzhongniao
#? 2
zhangsan
#? 3
lisi
#? 4
xiangli
#?
方法2:采用数组做变量
[root@shellbiancheng jiaobenlianxi]# cat select1.sh
#!/bin/bash
array=(linzhongniao zhangsan lisi xiangli)
select name in "${array[@]}"
do
echo $name
done
案例二:调整select循环菜单项的默认提示符及利用select变量打印数字序号。
[root@shellbiancheng jiaobenlianxi]# cat select2.sh
#!/bin/bash
PS3="Pls select a num fron menu:" PS3就是控制select循环的提示符
array=(linzhongniao zhangsan lisi xiangli)
select name in "${array[@]}"
do
echo "$REPLY $name" $REPLY变量用于获取菜单项对应的数字,也就是用户输入的数字
done
案例三:打印选择菜单,一键安装web服务
当用户输入1时,输出“start installing lamp”然后执行/server/scripts/lamp.sh,脚本内容输出“lamp is installed”后退出脚本;当用户输入2时,输出“start installing lnmp”然后执行/server/script/lnmp.sh,输出“lnmp is installed”后退出脚本;当输入3时退出当前菜单及脚本。当输入任何其他字符,给出提示“Input error”后退出脚本。要对执行的脚本进行相关条件判断,例如:脚本是否存在,是否可执行等。这个是第二种方法第一种用cat打印菜单。
[root@shellbiancheng ~]# cat webmenu2.sh
#!/bin/bash
export PATH="/usr/local/mysql/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/curl/bin:/root/bin"
path="/server/scripts"
RETVAL=0
[ -d "$path" ]|| mkdir -p $path
function Usage(){
echo $"Usage:you must input (1|2|3)"
}
function InstallService(){
if [ $# -ne 1 ];then
Usage
fi
local RETVAL=0
echo "start install ${1}"
sleep 2
if [ ! -x "$path/${1}.sh" ];then
echo "$path/lamp.sh does not exist or can not be exec."
else
source $path/lamp.sh
fi
}
function main(){
PS3="`echo pls input the num you want:`"
select var in "Install lamp" "Install lnmp" "exit"
do
case "$REPLY" in
1)
InstallService lamp
RETVAL=$?
;;
2)
InstallService lnmp
RETVAL=$?
;;
3)
echo bye.
return 3
;;
*)
echo "you must input (1|2|3)"
echo "input error"
;;
esac
done
exit $RETVAL
}
main