28_Shell語言——while和until循環(while, until, sleep)

     前文中介紹的for循環,在使用時必須先創建一個元素列表,以決定循環的次數,可是考慮下面這個例子:若是用戶輸入「quit」就退出程序,不然將用戶輸入的字符轉換爲大寫,如and轉換爲ANDexit轉換爲EXIT。這個例子沒法創建元素列表,由於沒法肯定用戶什麼時候輸入quit,也就沒法肯定要循環多少次。要解決這個問題,就須要引入一個新的機制:whileuntilwhileuntil尤爲適合循環次數未知的狀況,固然,對於循環次數已知的狀況,它們也一樣適用。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循環的使用方法

untilwhile循環很相似,都是當循環次數未知的時候使用。until的用法格式以下:

 

until 測試條件; do

 語句1

 語句2

 ...

done

 

while相反,until是當條件知足時,退出循環;而當條件不知足時就執行語句。事實上untilwhile兩者能夠互換,當對知足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
相關文章
相關標籤/搜索