shell编程中while与for的区别

在shell编程中经常用到循环,常用的循环有for和while循环两种。while循环默认以行读取文件,而for循环以空格读取文件切分文件,本篇就结合现网的一些使用示例说说二者的用法和区别。

一、常用语法

1、for循环

for循环常用的语法结构有如下几种:



<br />
for 变量 in seq字符串
for 变量 in `command`  " "
for 变量 in "@"或“*”
for((赋值;条件;运算语句))

2、while循环

while循环常用的语法结构有如下几种:



<br />
while [ $i -lt num ]
while true
while read a b c; do command done < filename
cat filename | while read a b c

二、行读取示例

这里以常见的df获取磁盘信息为例,了解下使用for和while的几种循环方法处理时的区别。先看下我写的脚本,内容如下:



<br />
#/bin/bash
## author: yangbk
## site: www.361way.com
## mail: itybku@139.com
## desc: test loop for in and while
df -hl|awk 'int(5) >30 ' > testfile
result=`df -hl|awk 'int(5) >30 '`
echo '******************* for testing *****************'
for i in result;do
        echoi
done
echo '******************* while echo test *************'
echo result | while read line
do
    echoline
done
echo '****************** while testing ****************'
df -hl|awk 'int(5) >30 '|while read line
do
    echoIP `hostname` line
done
echo '****************** while read file **************'
while read line
do
    echoIP `hostname` $line
done < testfile

上面的脚本执行时结果如下:

<br />



<br />
# sh forwhile.sh
******************* for testing *****************
/dev/sda3
9.5G
5.7G
3.4G
64%
/
/dev/sda2
39G
19G
18G
52%
/home
/dev/sda6
9.5G
7.1G
2.0G
78%
/usr
******************* while echo test *************
/dev/sda3 9.5G 5.7G 3.4G 64% / /dev/sda2 39G 19G 18G 52% /home /dev/sda6 9.5G 7.1G 2.0G 78% /usr
****************** while testing ****************
localhost /dev/sda3 9.5G 5.7G 3.4G 64% /
localhost /dev/sda2 39G 19G 18G 52% /home
localhost /dev/sda6 9.5G 7.1G 2.0G 78% /usr
****************** while read file **************
localhost /dev/sda3 9.5G 5.7G 3.4G 64% /
localhost /dev/sda2 39G 19G 18G 52% /home
localhost /dev/sda6 9.5G 7.1G 2.0G 78% /usr
可以看到,只有后面两种方法可以正常获取到我们想要的数据,前面两种方法在处理时和我们想要的结果都不一样。此示例得出的结果为:



<span style="color:#E53333;">1、while循环: 以行读取文件,默认分隔符是空格或者Tab;</span>



<span style="color:#E53333;">2、for循环: 以空格读取文件,也就是碰到空格,就开始执行循环体,所以需要以行读取的话,就要把空格转换成其他字符</span>。

三、ssh连接与wait

这里还是以一个测试脚本为例:



<br />
#!/bin/bash
## author: yangbk
## site: www.361way.com
## mail: itybku@139.com
## desc: test wait and ssh when use for in and while
# while loop
echo -en "\t";date
cat abc.txt|while read user ip
do
{
 ssh -o ConnectTimeout=10 user@ip "hostname" < /dev/null
 sleep 10s
} &
done
wait
echo "This is while loop."
echo -en "\t";date
sleep 10s
echo -e "\n"
# for loop
echo -en "\t";date
for line in `cat abc.txt|sed -e 's/ /--/g'`
do
{
 user=`echo $line|awk -F '--' '{print $1}'`
 ip=`echo $line|awk -F '--' '{print $2}'`
 ssh -oConnectTimeout=10 $user@$ip "hostname"
 sleep 10s
} &
done
wait
echo "This is for loop."
echo -en "\t";date
此示例的结果这里不再输出,具体可以使用该脚本ssh几台主机做个测试,测试后得到结果如下:



<span style="color:#E53333;">1、for循环: 循环体在后台执行,等待循环体全部执行结束,后面的命令接着执行。</span>



<span style="color:#E53333;">2、while循环: wait没起到作用,循环体在后台执行,后面的命令也同时在执行。循环体内有ssh、scp、sshpass的时候有执行一次循环就退出的情况,解决该问题方法有如下两种:</span>



<br />
  • a、使用ssh -n "command" ;
  • b、将while循环内加入null重定向,如 ssh "cmd" < /dev/null 将ssh 的输入重定向输入。
<br />

四、执行效率

在对大文件进行按行读取(for在读取文件时,可以for i in `cat filename`进行按行读取)的效率方面,<span style="color:#E53333;">经测试while 要更快一些</span>。测试脚本可以去<a href="https://github.com/361way/shell/blob/master/forwhile/timetest.sh" target="_blank" rel="noopener">我的github上去取</a>。while重定向读文件的方法还有另一种不常见的方法,有兴趣的可以看下我的另一篇 ---<a href="https://www.361way.com/readfile/240.html" target="_blank" rel="noopener">shell下读取文件的方法</a>。



<br />

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注