色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁技術文章
文章詳情頁

Unix系列shell程序編寫(下)

瀏覽:142日期:2024-06-26 14:40:06

Until語句

While語句中,只要某條件為真,則重復執(zhí)行循環(huán)代碼,until語句正好同while相反,該語句使循環(huán)代碼重復執(zhí)行,直到遇到某一條件為真才停止。

Until語句的結構如下: until command do command command … … done

可以用until語句替換上面?zhèn)浞莩绦虻膚hile語句,完成同樣的功能:

until [ $ANS != Y -a $ANS != y ]

for 循環(huán) 在介紹for循環(huán)之前,我們要學個非常有用的Unix命令:shift。我們知道,對于位置變量或命令行參數(shù),其個數(shù)必須是確定的,或者當Shell程序不知道其個數(shù)時,可以把所有參數(shù)一起賦值給變量$*。若用戶要求Shell在不知道位置變量個數(shù)的情況下,還能逐個的把參數(shù)一一處理,也就是在$1后為$2,在$2后面為$3等。在 shift命令執(zhí)行前變量$1的值在shift命令執(zhí)行后就不可用了。

示例如下:

#測試shift命令(x_shift.sh) until [ $# -eq 0 ] do echo '第一個參數(shù)為: $1 參數(shù)個數(shù)為: $#' shift done 執(zhí)行以上程序x_shift.sh: $./x_shift.sh 1 2 3 4

結果顯示如下:

第一個參數(shù)為: 1 參數(shù)個數(shù)為: 3 第一個參數(shù)為: 2 參數(shù)個數(shù)為: 2 第一個參數(shù)為: 3 參數(shù)個數(shù)為: 1 第一個參數(shù)為: 4 參數(shù)個數(shù)為: 0從上可知shift命令每執(zhí)行一次,變量的個數(shù)($#)減一,而變量值提前一位,下面代碼用until和shift命令計算所有命令行參數(shù)的和。

#shift上檔命令的應用(x_shift2.sh) if [ $# -eq 0 ] then echo 'Usage:x_shift2.sh 參數(shù)' exit 1 fi sum=0 until [ $# -eq 0 ] do sum=`expr $sum + $1` shift done echo 'sum is: $sum'

執(zhí)行上述程序:

$x_shift2.sh 10 20 15

其顯示結果為:

45

shift命令還有另外一個重要用途,Bsh定義了9個位置變量,從$1到$9,這并不意味著用戶在命令行只能使用9個參數(shù),借助shift命令可以訪問多于9個的參數(shù)。

Shift命令一次移動參數(shù)的個數(shù)由其所帶的參數(shù)指定。例如當shell程序處理完前九個命令行參數(shù)后,可以使用shift 9命令把$10移到$1。

在熟悉了shift命令后,我們一起看看,Bsh程序中非常有用的for循環(huán)語句,這種循環(huán)同上面說的while和until循環(huán)不同,for語句中的循環(huán)是否執(zhí)行并不由某個條件的真和假來決定,決定for循環(huán)是否繼續(xù)的條件是參數(shù)表中是否還有未處理的參數(shù)。

For語句的結構如下:

for variable in arg1 arg2 … argn do command command … … done

下面是for循環(huán)的簡單例子:

for LETTER in a b c d do echo $LETTER done

程序執(zhí)行結果如下:

a b c d

在上面計算參數(shù)和的例子中,我們可以用for循環(huán),實現(xiàn)如下:

#測試 for 程序(x_for.sh)

if [ $# -eq 0 ] then   echo 'Usage:x_for.sh 參數(shù)… …'   exit 1 fi sum=0 for I in $* do   sum=`expr $sum + $I` done echo 'sum is: $sum'

中斷循環(huán)指令

在程序循環(huán)語句中,我們有時候希望遇到某中情況時候結束本次循環(huán)執(zhí)行下次循環(huán)或結束這個循環(huán),這就涉及到兩條語句:continue和break。continue命令可使程序忽略其后循環(huán)體中的其他指令,直接進行下次循環(huán),而break命令則立刻結束循環(huán),執(zhí)行循環(huán)體后面的的語句。

#測試continue I=1 while [ $I -lt 10 ] do if [ $I -eq 3 ] then continue fi if [ $I -eq 7 ] then break fi echo '$Ic' done

執(zhí)行上面程序,結果如下:

12456789

與或結構

使用與/或結構有條件的執(zhí)行命令

Shell程序中可以使用多種不同的方法完成相同的功能,例如until和while語句就可以完成相同的功能,同樣,除了if-then-else結構可以使命令有條件的執(zhí)行外,$$和||操作符也能完成上述功能。在C語言中這兩個操作符分別表示邏輯與和邏輯或操作。在Bourne Shell中,用&&連接兩條命令的含義只有前面一條命令成功執(zhí)行了,后面的命令才會執(zhí)行。

&&操作的形式為:

command && command

例如語句:

rm $TEMPDIR/* && echo 'Files successfully removed'

只有rm命令成功執(zhí)行以后,才會執(zhí)行echo命令。若用if-then語句實現(xiàn)上述功能,形式為:

if rm $TEMPDIR/* then echo 'Files successfully removed' fi 相反,用||連接兩條命令的含義為只有第一條命令執(zhí)行失敗才執(zhí)行第二條命令,例如:

rm $TEMPDIR/* || echo 'File were not removed'

上面語句的等價形式為:

if rm $TEMPDIR/* then : else echo 'Files were not removed' fi 這兩種操作符可以聯(lián)合使用,如在下面的命令行中,只有command1和command2執(zhí)行成功后,command3才會執(zhí)行:

command1 && command2 && command3

下面的命令行表示只有command1成功執(zhí)行,command2不成功執(zhí)行時,才會執(zhí)行command3。

&&和||操作符可以簡化命令條件執(zhí)行的格式,但一般只用于一條命令的條件執(zhí)行。如果許多命令都使用這兩個操作符,那么整個程序的可讀性將變的很差,所以在多條命令的條件執(zhí)行時,最好采用可讀性好的if語句。

函數(shù)

現(xiàn)在我們介紹Shell程序中的函數(shù)部分,基本上任何高級語言都支持函數(shù)這個東西,能讓我們勝好多事情的東西,至少省的頻繁的敲擊相同的東西,好了come on Shell程序中的函數(shù)

函數(shù)又叫做子程序,可以在程序中的任何地方被調用,其格式如下:

函數(shù)名字() { command ... ... command; }

Shell程序的任何地方都可以用命令 '函數(shù)名字' 調用,使用函數(shù)的好處有兩點,一點是使用函數(shù)可以把一個復雜的程序化為多個模塊,易于管理,符合結構化程序的設計思想,另一個好處是代碼的重用。

Shell函數(shù)和Shel程序比較相似,它們的區(qū)別在于Shell程序在子Shell中運行,而Shell函數(shù)在當前Shell中運行。因此,在當前Shell中可以看到Shell函數(shù)對變量的修改。在任何Shell中都可以定義函數(shù),包括交互式Shell。

例如:

$dir() {ls -l;}

結果是我們在$后面打dir,其顯示結果同ls -l的作用是相同的。該dir函數(shù)將一直保留到用戶從系統(tǒng)退出,或執(zhí)行了如下所示的unset命令: $unset dir 下面的例子說明了函數(shù)還可以接受位置參數(shù):

$dir(){_ >echo 'permission  ln owner group  file sz last access >ls -l $*; >}

運行 dir a* 看產(chǎn)生什么結果

參數(shù)a*傳遞到dir函數(shù)中并且代替了$*

通常Shell程序將在子Shell中執(zhí)行,該程序對變量的改變只在子Shell中有效而在當前Shell中無效。'.'命令可以使Shell程序在當前Shell中執(zhí)行。用戶可以在當前Shell中定義函數(shù)和對變量賦值。通常用下面命令來重新初使化.profile對Shell環(huán)境的設置。 $ . .profile 由于看到這部分相對簡單,我們還是順便說說trap好了

使用trap命令進行例外處理

用戶編寫程序在程序運行時可能會發(fā)生一些例外情況,比如執(zhí)行該程序的用戶按中斷鍵或使用kill命令,或者控制終端突然與系統(tǒng)斷開等。unix系統(tǒng)中的上述情況會使系統(tǒng)向進程發(fā)一個信號,通常情況下該信號使進程終止運行。有時侯用戶希望進程在接到終止信號時進行一些特殊的操作。若進程在運行時產(chǎn)生一些臨時文件,又因接受到的信號而終止。那么該進程產(chǎn)生的臨時文件將保留下來。在bsh中,用戶可以使用trap命令修改進程接收到終止信號時進行的默認操作。 trap命令格式如下:

 trap command_string signals

多數(shù)系統(tǒng)中共有15種發(fā)給進程的信號,默認情況下大多數(shù)信號都會使程序終止。用戶最好查閱自己系統(tǒng)的文擋,看看本系統(tǒng)內使用的信號種類。除了信號為9(真正的kill信號)不能使用trap命令外,其他信號所帶來的操作都可以用trap命令進行指定。下面是trap命令中經(jīng)常使用的幾種信號:

信號 功能 1   掛起 2操作中斷 15  軟終止(kill信號)

若命令串中包含不只一條命令,必須使用引號將整個命令括起來,具體是單引號還是雙引號,由用戶是否需要變量替換決定。' '替換,' '不替換。

使用下面trap命令可以使程序在接收到掛起、中斷或kill信號時,首先把臨時文件刪除,然后退出:

trap 'rm $TEMPDIR/* $$;exit' 1 2 15

在上面例子中,當Shell讀取trap命令時,首先對$TEMPDIR和$$進行變量替換,替換之后的命令串將被保存在trap表中,若上例中trap命令使用單引號時,trap命令執(zhí)行時候,不進行變量替換,而把命令串 rm $TEMPDIR/* $$;exit 放到trap表中,當檢測到信號時,程序解釋執(zhí)行trap表中的命令串,此時進行變量替換。前面變量$TEMPDIR和$$的值為執(zhí)行trap指令時候的值,后一種情況中變量的值為程序接收到信號時候的值,所以 '、'一定要區(qū)分仔細。

下面命令的含義為用戶按二次中斷鍵后,程序才終止:

trap 'trap 2' 2

一般trap命令中的命令串中幾乎都包含exit語句,上面rm的例子若無exit語句,接收到信號rm命令執(zhí)行完后程序將掛起。但有時用戶也需要程序在接到信號后掛起,例如當終端和系統(tǒng)斷開后,用戶發(fā)出掛起信號,并執(zhí)行空命令,如下:

trap : 1

若用戶想取消前trap指令設置的命令串,可以再執(zhí)行trap命令,在命令中不指定命令串表示接收到信號后進行默認的操作,命令如下: trap 1

規(guī)范Shell

獲取UNIX類型的選項:

unix有一個優(yōu)點就是標準UNIX命令在執(zhí)行時都具有相同的命令行格式:

command -options parameters

如果在執(zhí)行Shell程序也采用上述格式,Bourne Shell中提供了一條獲取和處理命令行選項的語句,即getopts語句。該語句的格式為:

getopts option_string variable

其中option_string中包含一個有效的單字符選項。若getopts命令在命令行中發(fā)現(xiàn)了連字符,那么它將用連字符后面的字符同option_string相比較。若有匹配,則把變量variable的值設為該選項。若無匹配,則variable設為?。當getopts發(fā)現(xiàn)連字符后面沒有字符,會返回一個非零的狀態(tài)值。Shell程序中可以利用getopts的返回值建立一個循環(huán)。

下面代碼說明了date命令中怎么使用getopts命令處理各種選項,該程序除了完成unix的標準命令date的功能外,還增加了許多新的選項。 #新date程序 if [ $# -lt 1 ] then date else while getopts mdyDHMSTJjwahr OPTION do case $OPTION in m)date '+%m' d)date '+%d' y)date '+%y' D)date '+%D' H0date '+%H' M)date '+%M' S)date '+%S' T)date '+%T' j)date '+%j' J)date '+%y%j' w)date '+%w' a)date '+%a' h)date '+%h' r)date '+%r' ?)echo '無效的選項!$OPTION' esac done fi 有時侯選項中還帶一個值,getopts命令同樣也支持這一功能。這時需要在option_string中選項字母后加一個冒號。當getopts命令發(fā)現(xiàn)冒號后,會從命令行該選項后讀取該值。若該值存在,那么將被存在一個特殊的變量OPTARG中。如果該值不存在,getopts命令將在OPTARG中存放一個問號,并且在標準錯誤輸出上顯示一條消息。

下面的例子,實現(xiàn)拷貝一個文件,并給文件賦一個新的名字。-c選項指定程序拷貝的次數(shù),-v選項要求顯示新創(chuàng)建文件的文件名。

#--拷貝程序

COPIES=1 VERBOSE=N while getopts vc:OPTION do case $OPTION in c)COPIES=$OPTARG v)VERBOSE=Y ?)echo '無效參數(shù)!'   exit 1 esac done if [ $OPTIND -gt $# ] then echo 'No file name specified'   exit 2 fi shift 'expr $OPTIND - 1' FILE=$1 COPY=0 while [ $COPIES -gt $COPY ] do COPY='expr $COPY + 1' cp $FILE $ {FILE} $ {COPY} if [ VERBOSE = Y } then echo ${FILE} $ {COPY} fi done

規(guī)范Shell:

我們知道環(huán)境變量PS1是提示符,看下面程序chdir: if [ ! -d '$!' ] then echo '$1 is not a Directory' exit 1 fi cd $1 PS1=''pwd'>' export PS1

我們執(zhí)行:

 $chdir /usr/ice666

結果提示符號變成/usr/ice666>了嗎?沒有,為什么?

原因在于:chdir在子Shell中執(zhí)行,變量PS1的修改在當前Shell中也不會起作用,若要chdir完成意想中的功能,必須在當前Shell中執(zhí)行該命令。最好的方法就是把其改成一個函數(shù)并且在.profile文件中定義。但若要把函數(shù)放到單個文件中并在當前Shell中執(zhí)行,則需要使用 . 命令,并將chdir重寫成一個函數(shù),把其中的exit改寫成return。下面代碼是 .ice_ps的內容:

#--提示符 chdir() { if [ !-d '$1' ] then echo ' $1 is not a directory' return fi cd $1 PS1=''pwd'>' export PS1; }

然后我們在.profile文件中加入下面語句

.ice_ps

然后在切換目錄的時候,我們用chdir命令,結果是什么呢,自己實驗好了!   調試Shell程序

1>調試shell程序

用戶剛編寫完Shell程序中,不可避免的會有錯誤,這時我們可以利用Bsh中提供的跟蹤選項,該選項會顯示剛剛執(zhí)行的命令及參數(shù)。用戶可以通過set命令打開-x選項或在啟動Shell使用-x選項將Shell設置成跟蹤模式。例如有下面代碼ice_tx:

if [ $# -eq 0 ] then echo 'usage:sumints integer list' exit 1 fi sum=0 until [ $# -eq 0 ] do sum='expr $sum + $1' shift done echo $sum

我們用跟蹤模式運行:

$sh -x ice_tx 2 3 4 結果顯示: +[ 3 -eq 0 ] +sum=0 +[ 3 -eq 0 ] +expr 0+2 +sum=2 +shift +[ 2 -eq 0 ] +expr 2+3 +sum=5 +shift +[ 1 -eq 0 ] +expr 5+4 +sum=9 +[ 0 -eq 0 ] +echo 9 9

從上面可以看出,跟蹤模式下Shell顯示執(zhí)行的每一條命令以及該命令使用的變量替換后的參數(shù)值。一些控制字如if、then、until等沒顯示。 2>命令分組

Shell中若干命令可以組成一個單元一起執(zhí)行。為了標識一組命令,這些命令必須放到'()'或'{}'中。放在'()'中的命令將在子Shell中運行,而放在'{}'中的命令將在當前Shell中運行。子Shell中運行的命令不影響當前Shell的變量。當前Shell中運行的命令影響當前Shell的變量。

$NUMBER=2 $(A=2;B=2;NUMBER='expr $A+$B';echo $NUMBER) 結果為:4 $echo $NUMBER 結果為:2 如果把上面的()變成{},結果會是怎么樣的呢?

3>使用Shell分層管理器shl

UNIX是一個多道程序設計的操作系統(tǒng),一些UNIX系統(tǒng)利用這一特性提供了Shell層次管理器shl。使用shl用戶一次可以打開多個層次的Shell,其中活躍的Shell可以從終端上獲得輸入。但所有Shell的輸出都可在終端上顯示,除非顯示被禁止。

多個Shell中有一個為shl,當用戶在某個Shell中工作時,可以通過使用特殊字符(一般為Ctrl+z)返回shl。為了同其他Shell區(qū)別,shl中提示符為'>>>'。當用戶工作在Shell層次管理器中時,可以創(chuàng)建、激活和刪除Shell,下面是shl中使用的命令。

create name產(chǎn)生名為name的層次 delete name刪除名為name的層次 block name 禁止名為name的層次的輸出 unblock name  恢復名為name的層次的輸出 resume name激活名為name的層次 toggle 激活近來經(jīng)常使用的層次 name  激活名為name的層次

layers [-l] name  對于表中的每個層次,顯示其正在運行的進程的進程號,-l選項要求顯示詳細信息。

help  顯示shl命令的幫助信息 quit  退出shl以及所有被激活的層次 總結

在前面我們主要介紹了sh的變量、基本語法、程序設計等。如果掌握了這些內容,在學習其他UNIX下編程語言的時候,相信有一定的好處,我們說了,在大多數(shù)的UNIX中都提供Bourn Shell,而且很少有象sh這樣強大的腳本編輯語言了,是系統(tǒng)管理員和程序員的一筆財富,并且不需要額外的軟件環(huán)境,對文件等處理借助unix命令,實現(xiàn)起來比c實現(xiàn)還要簡單。

標簽: Unix系統(tǒng)
主站蜘蛛池模板: 国产欧美亚洲精品 | 国产无卡一级毛片aaa | 日韩美女一级片 | 成人影院人人免费 | 国产成人一区二区三区高清 | 欧美精品色视频 | 久久久免费 | 国产精品久久久久影院 | 久久精品国产精品青草色艺 | 美女亚洲视频 | 亚洲91| 国产一区二区三区在线观看免费 | 亚洲系列中文字幕一区二区 | 美日韩一区二区三区 | 免费国产不卡午夜福在线 | 日本一级爽毛片在线看 | 九九视频免费在线观看 | 一级做a爰片久久毛片看看 一级做a爰片久久毛片鸭王 | 欧美怡红院免费的视频 | 国产精品系列在线 | 国产精品成人自拍 | 成人精品在线视频 | 一本久道综合久久精品 | 国产欧美一区二区三区在线看 | 国产成人亚洲综合网站不卡 | 久久99久久99精品免观看 | 手机看片毛片 | 欧美一级别 | 欧美日韩另类综合 | 欧美透逼 | 久久久久久久久久免费视频 | 国产一区在线观看免费 | 久久九九久精品国产 | 1024国产欧美日韩精品 | 久草网在线视频 | 久色小说| 最新三级网址 | 久操精品视频 | 中文精品爱久久久国产 | 国产手机看片 | 日韩精品视频美在线精品视频 |