前面讨论e x p r时指出,循环时如果要加入计数,使用此命令。下面使用l s在f o r循环中列出
文件及其数目。
[root@localhost huangcd]# cat forcount
#!/bin/bashcounter=0
for files in *
do
counter=`expr $counter + 1`
done
echo "there are $counter files in `pwd` we need to process"
[root@localhost huangcd]# sh forcount
there are 76 files in /home/huangcd we need to process
[root@localhost huangcd]# ls|wc -l
76
嵌入循环可以将一个f o r循环嵌在另一个f o r循环内:
for 变量名1 in列表1
d o
for 变量名2 in 列表2
d o
命令1
. . .
d o n e
d o n e
下面脚本即为嵌入f o r循环,这里有两个列表A P P S和S C R I P T S。第一个包含服务器上应用
的路径,第二个为运行在每个应用上的管理脚本。对列表A P P S上的每一个应用,列表
S C R I P T S里的脚本将被运行,脚本实际上为后台运行。脚本使用t e e命令在登录文件上放一条
目,因此输出到屏幕的同时也输出到一个文件。查看输出结果就可以看出嵌入f o r循环怎样使
用列表S C R I P T S以执行列表A P P S上的处理。
[root@localhost huangcd]# cat audit_run
#!/bin/bash
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`
for loop in $APPS
do
for loop2 in $SCRIPTS
do
echo "system $loop now running $loop2 at $MY_DATE"|tee -a $LOGFILE $loop $loop2
done
done
u n t i l循环执行一系列命令直至条件为真时停止。u n t i l循环与w h i l e循环在处理方式上刚好
相反。一般w h i l e循环优于u n t i l循环,但在某些时候—也只是极少数情况下, u n t i l循环更加
有用。
u n t i l循环格式为:
until 条件
命令1
. . .
d o n e
条件可为任意测试条件,测试发生在循环末尾,因此循环至少执行一次—请注意这一点。
这段脚本不断的搜寻w h o命令中用户r o o t,变量I S - R O O T保存g r e p命令结果。
如果找到了r o o t,循环结束,并向用户s i m o n发送邮件,通知他用户r o o t已经登录,注意
这里s l e e p命令用法,它经常用于u n t i l循环中,因为必须让循环体内命令睡眠几秒钟再执行,
否则会消耗大量系统资源。
[root@localhost huangcd]# cat until_who
#!/bin/bash
IS_ROOT=`who|grep root`
until [ "$IS_ROOT" ]
do
sleep 5
done
echo "watch it.roots in"|mail root
[root@localhost huangcd]# sh until_who
[root@localhost huangcd]# mail
Mail version 8.1 6/6/93. Type ? for help.
"/var/spool/mail/root": 3 messages 1 new 3 unread
U 1 logwatch@localhost.l Sat Oct 26 11:35 113/3545 "Logwat"
U 2 logwatch@localhost.l Wed Dec 11 09:49 90/3152 "Logwat"
>N 3 root@localhost.local Wed Dec 11 16:09 15/646
& 3
Message 3:
From root@localhost.localdomain Wed Dec 11 16:09:29 2013
Date: Wed, 11 Dec 2013 16:09:29 +0800
From: root <root@localhost.localdomain>
To: root@localhost.localdomain
watch it.roots in
w h i l e循环可用于读取键盘信息。下面的例子中,输入信息被设置为变量F I L M,按< C t r l -
D >结束循环。
[root@localhost huangcd]# cat whileread
#!/bin/bash
echo "type ctrl+d to terminate"
echo -n "enter your most like file:"
while read FILE
do
echo "yeah,great file the $FILE"
done
[root@localhost huangcd]# sh whileread
type ctrl+d to terminate
enter your most like file:ddfdfdf
yeah,great file the ddfdfdf
dfsf
yeah,great file the dfsf
w h i l e循环最常用于从一个文件中读取数据,因此编写脚本可以处理这样的信息。
假定要从下面包含雇员名字、从属部门及其I D号的一个文件中读取信息。
可以用一个变量保存每行数据,当不再有读取数据时条件为真。w h i l e循环使用输入重定
向以保证从文件中读取数据。注意整行数据被设置为单变量$ L I N E .。
[root@localhost huangcd]# cat whileread
#!/bin/bash
while read LINE
do
echo $LINE
done < names.txt
[root@localhost huangcd]# sh whileread
LOUISE COUNFD:Account:acc343
fdfd fgsdfsd:fdgdsf:df4ere
dfasfasggg fgsd:gadsfas:re322LOUISE COUNFD:Account:acc343
fdfd fgsdfsd:fdgdsf:df4ere
dfasfasggg fgsd:gadsfas:re322LOUISE COUNFD:Account:acc343
输出时要去除冒号域分隔符,可使用变量I F S。在改变它之前保存I F S的当前设置。然后
在脚本执行完后恢复此设置。使用I F S可以将域分隔符改为冒号而不是空格或t a b键。这里有3
个域需要加域分隔,即N A M E、D E P T和I D。
为使输出看起来更清晰,对e c h o命令使用t a b键将域分隔得更开一些,脚本如下:
[root@localhost huangcd]# sh whilereadifs
LOUISE CONRAD ACCOUNTS ACC8987
PETER JAMES PAYROLL PR489
FRED TERMS CUSTOMER CUSO12
JAMES LENOD ACCOUNTS ACC887
[root@localhost huangcd]# cat whilereadifs
#!/bin/bash
SAVEDIFS=$IFS
IFS=:
while read NAME DEPT ID
do
echo -e "$NAME\t$DEPT\t$ID"
done<name1.txt
IFS=$SAVEDIFS
[root@localhost huangcd]# cat name1.txt
LOUISE CONRAD ACCOUNTS ACC8987
PETER JAMES PAYROLL PR489
FRED TERMS CUSTOMER CUSO12
JAMES LENOD ACCOUNTS ACC887