《Shell 编程》10_for 和 select 循环语句

《Shell 编程》10_for 和 select 循环语句

标签(空格分隔): Shell


文章目录

  • 《Shell 编程》10_for 和 select 循环语句
    • 10.1 for 循环语法结构
    • 10.2 for 循环范例
    • 10.3 Linux 系统产生随机数的 6 种方法
    • 10.4 select 循环语句介绍及语法
    • 10.5 select 循环范例

10.1 for 循环语法结构

1)变量取值型:

for 变量名 in 变量取值列表 #<== 变量名依次获取变量取值列表内容(以空格分隔),每次仅取一个
do
    cmd...
done
  • 在此结构中 “in 变量取值列表” 可以省略,省略时相当于 in “$@”,也就是使用 for i 就相当于使用 for i in “$@”。

2)C 语言型:

for((exp1; exp2; exp3))
do
    cmd...
done

10.2 for 循环范例

例 10-1 竖向打印 5、4、3、2、1 这 5 个数字。

#!/bin/bash
#for n in 5 4 3 2 1   #<== 直接列出元素
#for n in {5..1}      #<== 利用大括号 {} 生成数字序列
for n in `seq 5 -1 1` #<== 采用 seq 生成数字序列
do
    echo "$n"
done

例 10-2 获取当前目录下的目录或文件名,并将其作为变量列表打印输出。

#!/bin/bash
for filename in `ls`
do
    echo "$filename"
done

例 10-3 用 for 循环批量修改文件扩展名。

[root@web001 scripts]# ll test/
total 0
-rw-r--r-- 1 root root 0 Oct 26 12:47 test.gif
-rw-r--r-- 1 root root 0 Oct 26 12:47 ylt.gif
[root@web001 scripts]# cat 222.sh
#!/bin/bash
cd test
for filename in `ls|grep "gif$"`
do
        mv $filename `echo $filename|cut -d . -f1`.txt
done
[root@web001 scripts]# sh 222.sh
[root@web001 scripts]# ll test/
total 0
-rw-r--r-- 1 root root 0 Oct 26 12:47 test.txt
-rw-r--r-- 1 root root 0 Oct 26 12:47 ylt.txt
法 2:通过 rename 命令实现
[root@web001 test]# rename "txt" "gif" *.txt
[root@web001 test]# ll
total 0
-rw-r--r-- 1 root root 0 Oct 26 12:47 test.gif
-rw-r--r-- 1 root root 0 Oct 26 12:47 ylt.gif

例 10-4 在 Linux 下批量修改文件名,将 “_finished” 去掉。

[root@web001 test]# ll
total 4
-rw-r--r-- 1 root root 95 Oct 26 14:48 223.sh
-rw-r--r-- 1 root root  0 Oct 26 14:44 test_1_finished.jpg
-rw-r--r-- 1 root root  0 Oct 26 14:44 test_2_finished.jpg
[root@web001 test]# cat 223.sh
#!/bin/bash
for file in `ls *.jpg`
do
    mv $file `echo $file|sed 's/_finished//g'`
    #mv $file `echo "${file%_finished*}.jpg"`
done
[root@web001 test]# sh 223.sh
[root@web001 test]# ll
total 4
-rw-r--r-- 1 root root 99 Oct 26 14:49 223.sh
-rw-r--r-- 1 root root  0 Oct 26 14:44 test_1.jpg
-rw-r--r-- 1 root root  0 Oct 26 14:44 test_2.jpg

法 2:ls 结合 awk 实现

[root@web001 test]# ll
total 2
-rw-r--r-- 1 root root  0 Oct 26 14:44 test_1.jpg
-rw-r--r-- 1 root root  0 Oct 26 14:44 test_2.jpg
[root@web001 test]# ls|awk -F "." '{print $0,$1,$2}'
test_1.jpg test_1 jpg
test_2.jpg test_2 jpg
[root@web001 test]# ls|awk -F "." '{print $0,$1"_finished."$2}'
test_1.jpg test_1_finished.jpg
test_2.jpg test_2_finished.jpg
[root@web001 test]# ls|awk -F "." '{print "mv",$0,$1"_finished."$2}'
mv test_1.jpg test_1_finished.jpg
mv test_2.jpg test_2_finished.jpg
[root@web001 test]# ls|awk -F "." '{print "mv",$0,$1"_finished."$2}'|bash
[root@web001 test]# ll
total 2
-rw-r--r-- 1 root root  0 Oct 26 14:44 test_1_finished.jpg
-rw-r--r-- 1 root root  0 Oct 26 14:44 test_2_finished.jpg

法 3:通过 rename 实现

[root@web001 test]# rename "_finished" "" *.jpg
[root@web001 test]# ll
-rw-r--r-- 1 root root  0 Oct 26 14:44 test_1.jpg
-rw-r--r-- 1 root root  0 Oct 26 14:44 test_2.jpg

例 10-5 通过脚本实现仅 sshd、rsyslog、crond、network、sysstat 服务在开机时自启动。

root@web001 scripts]# for service in `systemctl list-unit-files|grep enabled|awk '{print $1}'`;do systemctl disable $service;done
root@web001 scripts]# for service in crond network rsyslog sshd sysstat;do systemctl enable $service;done
for service in `systemctl list-unit-files|grep enabled|awk '{print $1}'|grep -vE "crond|network|sshd|rsyslog|sysstat"`;do systemctl $service disable;done
systemctl list-unit-files|grep enabled|grep -vE "crond|sshd|network|rsyslog|sysstat"|awk '{print "systemctl disable", $1}'|bash

systemctl list-unit-files|egrep -v "crond|sshd|network|rsyslog|sysstat"|awk '{print "systemctl disable", $1}'|bash

systemctl list-unit-files|grep enabled|grep -vE "crond|sshd|network|rsyslog|sysstat"|awk '{print $1}'|sed -r 's#(.*)#systemctl disble \1#g'|bash

例 10-6 打印九九乘法表。

#!/bin/bash
COLOR='\E[47;30m'
RES='\E[0m'

for num1 in `seq 9`
do
    for num2 in `seq 9`
    do
        if [ $num1 -ge $num2 ]; then
            if ((num1*num2>9)); then
                echo -en "${COLOR}${num2}*${num1}=$((num1*num2))$RES "
            else
                echo -en "${COLOR}${num2}*${num1}=$((num1*num2))$RES  " 
            fi
        fi
    done
    echo " "
done

例 10-7 实现 mysql 分库备份脚本

#!/bin/bash
PATH="/application/mysql/bin:$PATH"
DBPATH=/tmp/backup
MYUSER=root
MYPASS=password
SOCKET="/data/3306/mysql.sock"
MYCMD=mysql -u$MYUSER -p$MYPASS -S $SOCKET
MYDUMP="mysqldump -u$MYUSER -p$MYPASS -S $SOCKET"
[ -d "$DBPATH" ] || mkdir $DBPATH
for dbname in `$MYCMD -e "show databases;"|sed '1,2d'|egrep -v "mysql|schema"`
do
    $MYDUMP $dbname|gzip >&DBANME/${dbname}_$(date + %F).sql.gz
done

例 10-8 实现 mysql 分表备份脚本

#!/bin/bash
PATH="/application/mysql/bin:$PATH"
DBPATH=/tmp/backup
MYUSER=root
MYPASS=password
SOCKET=/data/3306/mysql.sock
MYCMD="msyql -u$MYUSER -p$MYPASS -S $SOCKET"
MYDUMP="mysqldump -u$MYUSER -p$MYPASS -S $SOCKET"
[ -d $DBPATH ] || mkdir $DBPATH
for dbname in `$MYCMD -e "show databases"|sed '1,2d'|egrep -v "mysql|schema"`
do
    for table in `$MYCMD -e "show tables from $dbname;"|sed '1d'`
    do
        $MYDUMP $dbname $table|gzip >$DBPATH/${dbname}_$(date +%F)/${dbname}_${table}.sql.gz
    done
done

例 10-9 批量创建 5 个系统账号(ylt01-ylt05),并设置密码(密码为 8 位随机数,要求是字符和数字的混合)

#!/bin/bash
. /etc/init.d/functions
user="ylt"
passfile="/tmp/user.log"
for num in `seq -w 05`
do
    pass="`echo "test$RANDOM"|md5sum|cut -c3-10`"
    useradd $user$num &>/dev/null &&\
    echo "$pass"|passwd -stdin $user$num &>/dev/null &&\
    echo -e "user:$user$num\tpasswd:$pass">>$passfile
    if [ $? -eq 0 ]; then
        action "$user$num is ok" /bin/true
    else
        action "$user$num is fail" /bin/false
    fi
done
cat $passfile && >$passfile

10.3 Linux 系统产生随机数的 6 种方法

1)通过系统环境变量($RANDOM)实现

[root@web001 scripts]# echo $RANDOM
12846
  • RANDOM 的随机数范围是 0~32767。可以通过在输出的随机数后增加加密字符串,再一起执行 md5sum 操作并截取结果的后 n 位。
[root@web001 scripts]# echo ylt$RANDOM|md5sum|cut -c 1-5
06d50
#ylt 就是上述加密字符串

2)通过 openssl 产生随机数

[root@web001 scripts]# openssl rand -base64 8
s50Slkzo6VE=
  • 令数字与大小写字符相结合,并且带上特殊字符,可以达到很长的位数。

3)通过时间(date)获得随机数

[root@web001 scripts]# date +%s%N
1540551763039074396

4)通过 /dev/urandom 配合 chksum 生成随机数

[root@web001 scripts]# head /dev/urandom|cksum
4002297225 3674
  • /dev/random 设备存储着系统当前运行环境的实时数据。它可以看作系统在某个时候的唯一值。我们可以通过文件读取的方式,读到里面的数据。/dev/urandom 这个设备的数据与 random 里的一样,它是非阻塞的随机数发生器,读取操作不会产生阻塞。

5)通过 UUID 生成随机数

[root@web001 scripts]# cat /proc/sys/kernel/random/uuid
7f0f19cb-18dc-431e-b29e-a1c9e3ad9f38
  • UUID 码全程是通用唯一识别码(Universally Unique Identifier,UUID),它是一个软件建构的标准,亦为自由软件基金会(Open Software Foundation,OSF)的组织在分布式计算环境(Distributed Computing Environment,DCE)领域的一部分。
  • UUID 的目的是让分布式系统中的所有元素都有唯一的辨识信息,而不需要通过中央控制端来做辨识信息的指定。如此一来,每个人都可以创建不与其他人发生冲突的 UUID。它会让网络中任何一台计算机所产生的 UUID 码都是互联网整个服务器网络中唯一的编码。它的原信息会加入硬件、时间、机器当前的运行信息等。

6)使用 expect 附带的 mkpasswd 生成随机数

[root@web001 ~]# yum install -y expect
[root@web001 ~]# mkpasswd -l 9 -d 2 -c 3 -C 3 -s 1
6SnadM<4J

# -l (length of password, default = 9)
# -d (min # of digits, default = 2)
# -c (min # of lowewcase chars, default = 2)
# -C (min # of uppercase chars, default = 2)
# -s (min # of special chars, default = 1)

10.4 select 循环语句介绍及语法

1)select 循环语句为变量取值型

select 变量名 [ in 菜单取值列表 ]
do 
    cmd...
done
  • 与 for 循环不同的是,select 循环执行后会出现菜单项等待用户选择(不会自动循环所有变量列表),而用户输入的只能是菜单项前面的数字序号,每输入一次对应的序号就会执行一次循环,直到变量后面对应列表取完为止。

10.5 select 循环范例

例 10-10 用 select 循环打印菜单项的多种实现方法

1)直接使用列表字符串

[root@web001 scripts]# cat 242.sh
#!/bin/bash
select name in ylt yyy lll ttt
do
        echo $name
done
[root@web001 scripts]# sh 242.sh
1) ylt
2) yyy
3) lll
4) ttt
#? 1
ylt
#? 2
yyy
#? 3
lll
#? 4
ttt
#? ^C

2)采用数组做变量列表

[root@web001 scripts]# cat 242_1.sh
#!/bin/bash
array=(ylt yyy lll ttt)
select name in "${array[@]}"
do
        echo $name
done

3)把命令结果作为变量列表(菜单项)

[root@web001 scripts]# mkdir -p /tmp/test/{ylt,yyy,lll,ttt}
[root@web001 scripts]# cat 242_2.sh
#!/bin/bash
select name in `ls /tmp/test`
do
        echo $name
done

例 10-11 调整 select 循环菜单项的默认提示符及利用 select 变量打印数字序号。

[root@web001 scripts]# cat 244.sh
#!/bin/bash
PS3="please select a num from menu:"  # PS3 是系统环境变量用于控制 select 循环的提示符
select name in ylt yyy lll ttt
do
        echo -e "I guess you selected the menu is:\n $REPLY) $name"
done
[root@web001 scripts]# sh 244.sh
1) ylt
2) yyy
3) lll
4) ttt
please select a num from menu:1
I guess you selected the menu is:
 1) ylt
please select a num from menu:^C

你可能感兴趣的:(Shell,语法)