總第8篇
**本系列(玩轉Bash腳本)更多文章,請訪問:**[http://blog.csdn.net/column/details/wanbash.html](http://blog.csdn.net/column/details/wanbash.html)
和其他語言一樣Bash的循環結構中也有while語句。
### 基本結構
~~~
while 條件
do
循環體
done
~~~
和for語句一樣,它的循環體同樣是do…done結構。我們可以把while語句再折疊一下
~~~
while 條件;do
循環體
done
~~~
還能進一步折疊成一行體
~~~
while 條件;do 循環體;done
~~~
> Bash語句大都可以寫作一行,只不過可讀性差
和其他編程語言不同的是,Bash中的while語句用法是比較多樣的。可以根據while條件的不同,將while語句分為幾類。
### while條件
### 方括號[ ]
和if語句的條件相同。即操作符`[ ]`。關于`[ ]`的用法請參考之前的文章。
~~~
#!/bin/bash
n=1
while [ $n -le 10 ]
do
echo $n
let n++ #或者寫作n=$(( $n + 1 ))
done
~~~
在前面的文章中,已經講過了操作符`[ ]`和`test`語句是等價的,所以這里也可以用test語句來作條件。
### 終端命令
while的條件可以是各種終端的命令。包括外部命令或bash內建(built-in)命令都可以。因為命令都是有返回值的(可以用echo $?查看),命令執行的成功與否就是while條件的真或假。
以read命令來舉個例子
~~~
#!/bin/bash
while read var;do
echo "您輸入的是$var"
done
~~~
這個程序是個死循環,將不停地等待您的輸入,并回顯出來。
這里的命令可以是單個命令也可以是組合命令,比如用邏輯連接符連接的命令,或者管道、重定向組成的長命令
### 死循環
除了讓while條件恒成立外,編程語言都有一種簡潔的死循環寫法。比如C語言中典型的死循環條件是while(1),而java中的寫法是while(true)。?
而Bash中的寫法則簡單的多,只需要一個冒號。
~~~
#!/bin/bash
while :
do
echo I love you forever
done
~~~
這是一個死循環,執行之后請用按組合鍵Ctrl+C來終止它。?
此外,還有一種死循環寫法就是利用系統自帶的true命令(/bin/true)
~~~
#!/bin/bash
while /bin/true
do
echo I love you forever
done
~~~
由于我們的系統環境變量(PATH)中一般都包含了路徑/bin,所有我們也可以簡寫成`while true`
#### while實現菜單demo
我們或許曾經用C/C++在控制臺上輸出過菜單。這通常是一個do-while循環實現的,先輸出菜單的每個選項,然后等待輸入,?
根據不同的輸入執行不同的操作,然后循環再次輸出菜單……。?
bash中沒有do-while風格的循環,但是我們很容易用替代的方案實現該功能。用死循環+if/case條件判斷語句就夠了。
~~~
#!/bin/bash
#菜單demo
while :
do
echo #輸出空行
echo "========================="
echo " 1:輸出成績單"
echo " 2:輸出課程表"
echo " 3:輸出空閑教室"
echo " q:退出菜單"
echo "========================="
read -p"請輸入:" input
case $input in
1)echo "稍等,正在為您輸出成績單";;
2)echo "稍等,正在為您輸出課程表";;
3)echo "稍等,正在為您輸出空閑教";;
q|Q) exit
esac
done
~~~
## while與重定向
while語句可以聯合重定向(>和<)一起使用。
### while和輸入重定向<
格式為
~~~
while 命令
do
循環體
done < 文件名
~~~
相當于將文件內容逐行傳遞給while后面的命令(類似管道),然后再執行循環體。?
當循環體為空的時候,這個結構的功能通常和cat沒有兩樣,比如:
~~~
while grep "love"
do
done < letter
~~~
從文件letter中查找love這個單詞,其實和cat letter|grep “love”沒什么兩樣。
這個結構更習慣的用法和read聯用,來將文件內容逐行取出,賦值給read后面的變量。比如:
~~~
#!/bin/bash
#從/etc/passwd文件中讀取用戶名并輸出
oldIFS=$IFS #IFS是文件內部分隔符
IFS=":" #設置分隔符為:
while read username var #var變量不可少
do
echo "用戶名:$username"
done < /etc/passwd
IFS=$oldIFS
~~~
熟悉/etc/passwd文件結構的朋友都知道這個文件的每一行包含了一個用戶的大量信息(用戶名只是第一項)。
這里我們實際只輸出了用戶名。但是注意while的read后面除變量username外還有個var,盡管我們并不輸出這個變量的值。
但它卻必不可少,如果我們寫成`while read username`那么username的值等于passwd文件這一整行的內容(IFS=”:”也就不起作用了)
> bash中,只有當有多個變量要從一行文本賦值的時候,才嘗試去用IFS來分割,然后賦值。
### while和輸出重定向>
格式為
~~~
while 命令
do
循環體
done > 文件名
~~~
這個結構會將命令的輸出,以及循環體中的標準輸出都重定向到指定的文件中。?
比如:
~~~
#!/bin/bash
#每隔10分鐘,ping一下局域網內主機192.168.1.101,
#并把結果記錄到ping.txt文件中
while date
do
ping -c5 192.168.1.101 >/dev/null 2>&1
if [ $? = 0 ];then
echo OK
else
echo FAIL
fi
sleep 600 #600秒是10分鐘
done > ping.txt
~~~
我們來cat一下ping.txt文件,看一看:
~~~
2015年 01月 31日 星期六 16:03:13 CST
OK
~~~
這是ping.txt中的一條記錄
**本系列(玩轉Bash腳本)更多文章,請訪問:**[http://blog.csdn.net/column/details/wanbash.html](http://blog.csdn.net/column/details/wanbash.html)