前文中介紹的for循環,在使用時必須先創建一個元素列表,以決定循環的次數,可是考慮下面這個例子:若是用戶輸入「quit」就退出程序,不然將用戶輸入的字符轉換爲大寫,如and轉換爲AND,exit轉換爲EXIT。這個例子沒法創建元素列表,由於沒法肯定用戶什麼時候輸入quit,也就沒法肯定要循環多少次。要解決這個問題,就須要引入一個新的機制:while和until。while和until尤爲適合循環次數未知的狀況,固然,對於循環次數已知的狀況,它們也一樣適用。shell
1、while的使用方法apache
while的基本格式爲:vim
while 測試條件; dobash
語句1app
語句2ssh
...tcp
doneide
它的意思是當條件知足時,就執行循環,直到條件不知足,就退出循環。它和if的用法有些類似,只不過if只執行一次,而while會對條件反覆測試,反覆執行,直到條件不知足爲止。那麼如何使條件不知足呢?這就須要在循環體中改變初始的測試條件中相應變量的值,若是不改變,那麼就會造成死循環。oop
2、while循環的實例演示測試
例1. 如今使用while循環來計算100之內全部正整數的和:
[root@localhost tutor]# vimsum_while.sh
#!/bin/bash Sum=0 Count=1 while [ $Count -le 100 ]; do Sum=$[$Sum+$Count] let Count++ done echo $Sum
[root@localhost tutor]# bashsum_while.sh
5050
例2. 計算100之內全部偶數的和;
[root@localhost tutor]# vimeven_sum_while.sh
#!/bin/bash EvenSum=0 Count=0 while [ $Count -le 100 ]; do letEvenSum+=Count let Count+=2 # 使用+=能夠表示自身加上一個數 done echo $EvenSum
[root@localhost tutor]# basheven_sum_while.sh
2550
這個程序還能夠寫成如下形式:
[root@localhost tutor]# vimeven_sum_while.sh
#!/bin/bash EvenSum=0 Count=0 while [ $Count -le 100 ];do if [$[$Count%2] -eq 0 ];then letEvenSum+=$Count fi let Count++ done echo $EvenSum # 雖然這種寫法較前一種方法看起來更復雜,但它的擴展性更好,好比能夠作任意奇數的和,3倍數的和等等
[root@localhost tutor]# basheven_sum_while.sh
2550
若是要遍歷文件中的每一行,可使用while循環配合輸入重定向的方式,在done後面重定向要讀取的文件,其用法以下:
whileread LINE; do
statement1
statement2
...
done< /Path/To/Somefile
例3.若是用戶的ID號爲偶數,則顯示其名稱和shell;對全部用戶執行此操做:
[root@localhost tutor]# vimread_line.sh
#!/bin/bash while read LINE; do # 這裏的read LINE表示讀取/etc/passwd這個文件的一行,將讀到的內容放進LINE這個變量中 Uid=`echo$LINE | cut -d: -f3` if [ $[$Uid%2]-eq 0 ]; then echo$LINE | cut -d: -f1,7 fi done < /etc/passwd
[root@localhost tutor]# bashread_line.sh
root:/bin/bash daemon:/sbin/nologin lp:/sbin/nologin shutdown:/sbin/shutdown mail:/sbin/nologin uucp:/sbin/nologin games:/sbin/nologin ftp:/sbin/nologin rpc:/sbin/nologin avahi-autoipd:/sbin/nologin nfsnobody:/sbin/nologin haldaemon:/sbin/nologin gdm:/sbin/nologin ntp:/sbin/nologin apache:/sbin/nologin saslauth:/sbin/nologin sshd:/sbin/nologin tcpdump:/sbin/nologin user1:/bin/bash user3:/bin/bash user5:/bin/bash user7:/bin/bash user9:/bin/bash hello:/bin/tcsh hadoop:/bin/bash
例4:轉換用戶輸入的字符爲大寫,除了quit(碰見quit退出):
[root@localhost tutor]# vimquit_by_user.sh
#!/bin/bash read -p "A string: " String while [ "$String" != 'quit' ]; do echo $String |tr 'a-z' 'A-Z' read -p"Next [quit for exit]: " String done
[root@localhost tutor]# bashquit_by_user.sh
A string: sd gfdg SD GFDG Next [quit for exit]: adf!fdsf@ ADF!FDSF@ Next [quit for exit]: exit EXIT Next [quit for exit]: quit [root@localhost tutor]#
例5、使用while循環統計/etc/rc.d/init.d/functions中#開頭的行數;
[root@localhost tutor]# vimnum_lines_while.sh
#!/bin/bash Num=0 while read LINE; do echo $LINE |grep "^[[:space:]]*#" &> /dev/null && let Num++ # 考慮以#開頭的,而且考慮以空格和#開頭的行 # 使用&&能夠代替if done < /etc/rc.d/init.d/functions echo "Total $Num lines start with #."
[root@localhost tutor]# bashnum_lines_while.sh
Total 70 lines start with #.
3、until循環的使用方法
until和while循環很相似,都是當循環次數未知的時候使用。until的用法格式以下:
until 測試條件; do
語句1
語句2
...
done
和while相反,until是當條件知足時,退出循環;而當條件不知足時就執行語句。事實上until和while兩者能夠互換,當對知足while的條件取反時,就是until。
4、until循環的實例演示
例6. 使用until改寫例1,計算100之內全部正整數的和:
[root@localhost tutor]# vimsum_until.sh
#!/bin/bash Sum=0 Count=1 until [ $Count -gt 100 ]; do # while中使用的是le,until和while的條件相反 letSum+=$Count let Count++ done echo $Sum
[root@localhost tutor]# bashsum_until.sh
5050
例7. 計算100之內全部偶數的和以及奇數的和;在一個循環中實現;
[root@localhost tutor]# vimuntil_odd_even.sh
#!/bin/bash SumOdd=0 SumEven=0 i=1 until [ $i -gt 100 ];do if [ $[$i%2]-eq 0 ];then letSumOdd+=$i else letSumEven+=$i fi let i++ done echo " Odd Sum: $SumOdd. Even Sum: $SumEven"
[root@localhost tutor]# bashuntil_odd_even.sh
Odd Sum: 2550. EvenSum: 2500
例8. 使用until改寫例4,轉換用戶輸入的字符爲大寫,除了quit(碰見quit退出):
[root@localhost tutor]# vimquit_until.sh
#!/bin/bash read -p "A String: " String until [ "$String" == 'quit' ]; do # while循環中當$String不等於quit時執行,until與之相反 echo $String |tr 'a-z' 'A-Z' read -p"Next [quit for Exit]: " String done
[root@localhost tutor]# bashquit_until.sh
A String: sdf opq SDF OPQ Next [quit for Exit]: 123#fsd 123#FSD Next [quit for Exit]: Quit QUIT Next [quit for Exit]: quit
例9、每隔5秒查看hadoop用戶是否登陸,若是登陸,顯示其登陸並退出;不然,顯示當前時間,並說明hadoop還沒有登陸:
這裏須要引入一個新命令sleep,這個命令表示休眠,後面的參數接秒數
[root@localhost tutor]# mansleep
SLEEP(1) UserCommands SLEEP(1)
NAME
sleep - delayfor a specified amount of time
SYNOPSIS
sleep NUMBER[SUFFIX]...
若是要肯定當前登錄的用戶,可使用who命令,而要肯定hadoop用戶是否登錄了,可使用grep命令:
[root@localhost tutor]# vimhadoop_login.sh
#!/bin/bash until who | grep "^hadoop" &> /dev/null; do # 使用who命令能夠查看當前登錄的用戶 # 因爲who是個命令,而不是一個表達式,因此不須要[] date sleep 5 done echo "Welcom back, hadoop!"
爲了更好的理解上述程序的邏輯,能夠將其改寫爲:
[root@localhost tutor]# vimhadoop_login.sh
#!/bin/bash who | grep "^hadoop" &> /dev/null RetVal=$? # 先執行一次 who 和 grep命令 # 而後取出執行狀態返回值 until [ $RetVal-eq 0 ]; do # 若是執行狀態返回值爲0,表示who和grep命令執行成功了,就中止執行循環體 date sleep 5 who | grep"^hadoop" &> /dev/null Retval=$? # 若是date和sleep命令執行了,就再執行一次who和grep命令,以檢查hadoop用戶是否登錄 done echo "Welcomback, hadoop!"
[root@localhost tutor]# bashhadoop_login.sh
Sat Aug 16 09:55:37 EDT 2014 Sat Aug 16 09:55:42 EDT 2014 Sat Aug 16 09:55:47 EDT 2014 # 此時開啓另外一個終端,用Hadoop用戶登錄 Welcom back, hadoop!
例10. 寫一個腳本:
1) 顯示一個菜單給用戶:
d|D) show disk usages.
m|M) show memory usages.
s|S) show swap usages.
*) quit.
2) 當用戶給定選項後顯示相應的內容;
當用戶選擇完成,顯示相應信息後,不退出;而讓用戶再一次選擇,再次顯示相應內容;除了用戶使用quit;
[root@localhost tutor]# vimshow_disk.sh
#!/bin/bash cat <<EOF d|D) show disk usages. m|M) show memery usages. s|S) show swap usages. quit) quit EOF read -p "Input your choice [quit means exit]: "Char until [ "$Char" == 'quit' ]; do case $Char in d|D) df -lh ;; m|M) free -m |grep "^Me" ;; s|S) free -m |grep "^Sw" ;; *) echo"Input Errors." ;; esac read -p"Input your choice [quit means exit]:" Char done
[root@localhost tutor]# bashshow_disk.sh
d|D) show disk usages. m|M) show memery usages. s|S) show swap usages. quit) quit Input your choice [quit means exit]: d Filesystem Size Used Avail Use% Mounted on /dev/mapper/VolGroup-lv_root 23G 4.6G 17G 22% / tmpfs 499M 112K 499M 1% /dev/shm /dev/sda1 485M 35M 426M 8% /boot /dev/sdb3 9.9G 36M 9.7G 1% /mydata Input your choice [quit means exit]:M Mem: 996 358 638 0 63 114 Input your choice [quit means exit]:s Swap: 3051 0 3051 Input your choice [quit means exit]:a Input Errors. Input your choice [quit means exit]:quit