Bash流控十二手

在前几天的的文章中,《[原创]Shell脚本大量示例,你会几个?》、《[原创]Shell脚本生产示例,你努力学习了吗?》给大家讲解了shell脚本基础和shell编程的大量实例,如需要查看历史文章,请点击公众号的【文章导航】→ [shell系列文章]查阅,我们在今天的文章中,继续为大家带来shell脚本编程讲解!

一、case语句用法演示

case的一个有效用法是提示用户响应以决定是否继续进程。这里提示输入y以继续处理,n退出。如果用户输入Y、y或yes,处理继续执行case语句后面部分。如果用户输入N、n或no或其他响应,用户退出脚本。
#!/bin/sh
# caseans.sh
echo -n "Do you wish to proceed [y..n] :"
read ANS
case $ANS in
        y|Y|yes|Yes) echo "yes is selected"
        ;;
        n|N) echo "no is selected"
        exit 0  # no error so only use exit 0 to terminate
        ;;
        *) echo "`basename $0` : Unknow response" >&2
        exit 1
        ;;
esac    
# if we are here then a y|Y|yes|Yes was selected only.
运行脚本,输入无效响应,得结果:
[root@localhost ~]# ./caseans.sh 
Do you wish to proceed [y..n] :df
caseans.sh : Unknow response
给出有效响应:
[root@localhost ~]# ./caseans.sh 
Do you wish to proceed [y..n] :y
yes is selected

二、case与命令参数传递

可以使用case控制到脚本的参数传递。下面脚本中,测试特定变量$#,它包含传递的参数个数,如果不等于1,退出并显示可用信息。然后case语句捕获下列参数: passwd、start、stop或help,相对于每一种匹配模式执行进一步处理脚本。如果均不匹配,显示可用信息到标准错误输出。
#!/bin/sh
# caseparam.sh
if [ $# != 1 ]; then
        echo "Usage:`basename $0`[start|stop|help]" >&2
        exit 1
fi      
# assign the parameter to the variable OPT
OPT=$1
case $OPT in
        start) echo "starting.. `basename $0`"
        # code here to start a process
        ;;
        stop) echo "stopping.. `basename $0`"
        # code here to stop a process
        ;;
        help) 
        # code here to display a help page
        ;;
        *) echo "Usage:`basename $0`[start|stop|help]"
        ;;
esac
运行脚本,输入无效参数:
[root@localhost ~]# ./caseparam.sh what
Usage:caseparam.sh[start|stop|help]
输入有效参数,结果为:
[root@localhost ~]# ./caseparam.sh stop
stopping.. caseparam.sh

三、case语句捕获输入并执行空命令

不一定要在匹配模式后加入命令,如果你原本不想做什么,只是在进一步处理前过滤出意外响应,这样做是一种好办法。如果要运行对应于一个会计部门的帐目报表,必须首先在决定运行报表的类型前确认用户输入一个有效的部门号,匹配所有可能值,其他值无效。用case可以很容易实现上述功能。下面的脚本中如果用户输入部门号不是234、453、655或454,用户退出并返回可用信息。一旦响应了用户的有效部门号,脚本应用同样的技术取得报表类型,在case语句末尾显示有效的部门号和报表类型.
#!/bin/sh
# casevaild.sh
echo -n "Enter the account dept No: :"
read ACC
case $ACC in
        234);;
        453);;
        655);;
        454);;
        *) echo "`basename $0`: Unknown dept No:" >&2
        echo "try ... 234,453,655,454"
        exit 1
        ;;
esac
# if we are here, then we have validated the dept no
echo "1 . post"
echo "2 . prior"
echo -n "Enter the type of report:"
read ACC_TYPE
case $ACC_TYPE in
        1) TYPE=post
        ;;
        2) TYPE=prior;;
        *) echo "`basename $0`: Unknown account type." >&2
        exit 1
        ;;
esac
# if we are here the we are validated!
echo "now running report for dept $ACC for the type $TYPE"
# run the command reprot...
输入有效部门号,该脚本不同运行输入情况的显示结果:
[root@localhost ~]# ./casevalid.sh 
Enter the account dept No: :234
1 . post
2 . prior
Enter the type of report:2
now running report for dept 234 for the type prior
输入无效部门号,该脚本不同运行输入情况的显示结果:
[root@localhost ~]# ./casevalid.sh 
Enter the account dept No: :432
casevalid.sh: Unknown dept No:
try ... 234,453,655,454
输入无效的报表类型,该脚本不同运行输入情况的显示结果:
[root@localhost ~]# ./casevalid.sh 
Enter the account dept No: :655
1 . post
2 . prior
Enter the type of report:4
casevalid.sh: Unknown account type.

四、使用case语句实现缺省变量值设定

如果在读变量时输入回车键,不一定总是退出脚本。可以先测试是否已设置了变量,如果未设置,可以设置该值。下面的脚本中,要求用户输入运行报表日期。如果用户输入回车键,则使用缺省日期星期六,并设置为变量when的取值。如果用户输入另外一天,这一天对于case语句是运行的有效日期,即星期六、星期四、星期一。注意,这里结合使用了日期缩写作为捕获的可能有效日期。
#!/bin/sh
# caserep.sh
echo "      Weekly Report"
echo -n "What day do you want to run report [Saturday] :"
# if just a return is hit then except default which is Saturday
read WHEN
echo "validating .. ${WHEN:="Saturday"}"
case $WHEN in
        Monday|MONDAY|mon)
        ;;
        Sunday|SUNDAY|sun)
        ;;
        Saturday|SATURDAY|sat)
        ;;
        *)
        echo "Are you nuts! this report can only be run on " >&2
        echo " on a Saturday, Sunday or Monday" >&2
        exit 1
        ;;
esac    
echo "Report to run on $WHEN"
# command here to submitted actual report run
对于正确输入,执行结果如下:
[root@localhost ~]# ./caserep.sh 
                Weekly Report
What day do you want to run report [Saturday] :
validating .. Saturday
Report to run on Saturday
对于错误的输入,执行结果如下:
[root@localhost ~]# ./caserep.sh 
                Weekly Report
What day do you want to run report [Saturday] :Tuesday
validating .. Tuesday
Are you nuts! this report can only be run on 
on a Saturday, Sunday or Monday

五、简单的for循环

此例仅显示列表1 2 3 4 5,用变量名访问列表
#!/bin/sh
# for_i.sh
for loop in 1 2 3 4 5
do
        echo $loop
done
运行上述脚本,输出:
[root@localhost ~]# ./for_i.sh 
1
2
3
4
5

六、使用for语句打印字符串列表

下面for循环中,列表包含字符串“orange red blue grey”,命令为echo,变量名为loop,echo命令使用$loop反馈出列表中所有取值,直至列表为空。
#!/bin/sh
# forlist.sh
for loop in "orange red blue grey"
do
        echo "$loop"
done
脚本执行结果:
[root@localhost ~]# ./forlist.sh
orange red blue grey

七、for循环遍历目录下的文件

对for循环使用ls命令这个循环执行ls命令,打印当前目录下所有文件
#!/bin/sh
# forls.sh
for loop in `ls `
do
        echo $loop
done
脚本执行结果如下:
[root@localhost ~]# ./forls.sh
anaconda-ks.cfg
a.sql
a.txt
aw.txt
b.tx
b.txt

八、for循环遍历参数

在f o r循环中省去i n列表选项时,它将接受命令行位置参数作为参数。实际上即指明:for params in"$@"或者for params in"$*",下面的例子不使用i n列表选项, for循环查看特定参数$@$*,以从命令行中取得参数
#!/bin/sh
# forparam2
for params
do
        echo "You supplied $params as a command line option"
done
下面的脚本包含in "$@",结果与上面的脚本相同:
#!/bin/sh
# forparam3
for params in "$@"
do
        echo "You supplied $params as a command line option"
done

九、for循环实现查找文件

如果要查看一系列文件,可在for循环里使用find命令,利用命令行参数,传递所有要查阅的文件.
#!/bin/sh
# forfind.sh
for loop
do
        find / -name $loop -print
done

十、使用for循环备份文件

可以用for循环备份所有文件,只需将变量作为cp命令的目标参数。这里有一变量.bak,当在循环中使用cp命令时,它作为此命令目标文件名。列表命令为ls
#!/bin/sh
# forbak.sh
suffix=".bak"
for loop in `ls `
do
        cp $loop $loop$suffix
done

十一、使用for批量删除空文件

下面的例子中, sed用于删除所有空文件,并将输出导至以.HOLD。 mv为扩展名的新文件中,mv将这些文件移至初始文件中。
#!/bin/sh
# forsed.sh
for files in `ls LPSO*`
do
        sed -e "/^$/d" $files >$files.HOLD
        mv $files.HOLD $files
done

十二、for循环嵌入示例

下面脚本即为嵌入for循环,这里有两个列表APPS和SCRIPTS。第一个包含服务器上应用的路径,第二个为运行在每个应用上的管理脚本。对列表APPS上的每一个应用,列表SCRIPTS里的脚本将被运行,脚本实际上为后台运行。脚本使用tee命令在登录文件上放一条目,因此输出到屏幕的同时也输出到一个文件。查看输出结果就可以看出嵌入for循环怎样使用列表SCRIPTS以执行列表APPS上的处理。
#!/bin/sh
# audit_run.sh
APPS="/apps/accts /apps/claims /apps/stock /apps/serv"
SCRIPTS="audit.check report.run cleanup"
LOGFILE=audit.log
MY_DATE=`date +%H:%M" on "%d/%m%Y`
# outer loop
for loop in $APPS
do      
        # inner loop
        for loop2 in $SCRIPTS
        do      
                echo "system $loop now running $loop2 at $MY_DATE" | tee -a\
                 $LOGFILE $loop $loop2 &
         done    
done
程序的运行结果如下:
tee: /apps/accts: No such file or directory
tee: /apps/accts: No such file or directory
system /apps/accts now running report.run at 20:18 on 21/112010
tee: /apps/accts: No such file or directory
system /apps/accts now running cleanup at 20:18 on 21/112010
tee: /apps/claims: No such file or directory
system /apps/claims now running audit.check at 20:18 on 21/112010
tee: /apps/claims: No such file or directory
system /apps/claims now running report.run at 20:18 on 21/112010
tee: /apps/claims: No such file or directory
system /apps/claims now running cleanup at 20:18 on 21/112010
tee: /apps/stock: No such file or directory
system /apps/stock now running audit.check at 20:18 on 21/112010
tee: /apps/stock: No such file or directory
system /apps/stock now running report.run at 20:18 on 21/112010
tee: /apps/stock: No such file or directory
system /apps/stock now running cleanup at 20:18 on 21/112010
tee: /apps/serv: No such file or directory
system /apps/serv now running audit.check at 20:18 on 21/112010
[root@localhost ~]# system /apps/accts now running audit.check at 20:18 on 21/112010
tee: /apps/serv: No such file or directory
system /apps/serv now running report.run at 20:18 on 21/112010
tee: /apps/serv: No such file or directory
system /apps/serv now running cleanup at 20:18 on 21/112010


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章