av一区二区在线观看_亚洲男人的天堂网站_日韩亚洲视频_在线成人免费_欧美日韩精品免费观看视频_久草视

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Unix系列shell程序編寫(xiě)(下)

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

Until語(yǔ)句

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

Until語(yǔ)句的結(jié)構(gòu)如下: until command do command command … … done

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

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

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

示例如下:

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

結(jié)果顯示如下:

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

#shift上檔命令的應(yīng)用(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

其顯示結(jié)果為:

45

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

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

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

For語(yǔ)句的結(jié)構(gòu)如下:

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

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

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

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

a b c d

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

#測(cè)試 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)語(yǔ)句中,我們有時(shí)候希望遇到某中情況時(shí)候結(jié)束本次循環(huán)執(zhí)行下次循環(huán)或結(jié)束這個(gè)循環(huán),這就涉及到兩條語(yǔ)句:continue和break。continue命令可使程序忽略其后循環(huán)體中的其他指令,直接進(jìn)行下次循環(huán),而break命令則立刻結(jié)束循環(huán),執(zhí)行循環(huán)體后面的的語(yǔ)句。

#測(cè)試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í)行上面程序,結(jié)果如下:

12456789

與或結(jié)構(gòu)

使用與/或結(jié)構(gòu)有條件的執(zhí)行命令

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

&&操作的形式為:

command && command

例如語(yǔ)句:

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

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

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

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

上面語(yǔ)句的等價(jià)形式為:

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

command1 && command2 && command3

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

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

函數(shù)

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

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

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

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

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

例如:

$dir() {ls -l;}

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

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

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

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

通常Shell程序?qū)⒃谧覵hell中執(zhí)行,該程序?qū)ψ兞康母淖冎辉谧覵hell中有效而在當(dāng)前Shell中無(wú)效。'.'命令可以使Shell程序在當(dāng)前Shell中執(zhí)行。用戶(hù)可以在當(dāng)前Shell中定義函數(shù)和對(duì)變量賦值。通常用下面命令來(lái)重新初使化.profile對(duì)Shell環(huán)境的設(shè)置。 $ . .profile 由于看到這部分相對(duì)簡(jiǎn)單,我們還是順便說(shuō)說(shuō)trap好了

使用trap命令進(jìn)行例外處理

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

 trap command_string signals

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

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

若命令串中包含不只一條命令,必須使用引號(hào)將整個(gè)命令括起來(lái),具體是單引號(hào)還是雙引號(hào),由用戶(hù)是否需要變量替換決定。' '替換,' '不替換。

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

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

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

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

trap 'trap 2' 2

一般trap命令中的命令串中幾乎都包含exit語(yǔ)句,上面rm的例子若無(wú)exit語(yǔ)句,接收到信號(hào)rm命令執(zhí)行完后程序?qū)炱?。但有時(shí)用戶(hù)也需要程序在接到信號(hào)后掛起,例如當(dāng)終端和系統(tǒng)斷開(kāi)后,用戶(hù)發(fā)出掛起信號(hào),并執(zhí)行空命令,如下:

trap : 1

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

規(guī)范Shell

獲取UNIX類(lèi)型的選項(xiàng):

unix有一個(gè)優(yōu)點(diǎn)就是標(biāo)準(zhǔn)UNIX命令在執(zhí)行時(shí)都具有相同的命令行格式:

command -options parameters

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

getopts option_string variable

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

下面代碼說(shuō)明了date命令中怎么使用getopts命令處理各種選項(xiàng),該程序除了完成unix的標(biāo)準(zhǔn)命令date的功能外,還增加了許多新的選項(xiàng)。 #新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 '無(wú)效的選項(xiàng)!$OPTION' esac done fi 有時(shí)侯選項(xiàng)中還帶一個(gè)值,getopts命令同樣也支持這一功能。這時(shí)需要在option_string中選項(xiàng)字母后加一個(gè)冒號(hào)。當(dāng)getopts命令發(fā)現(xiàn)冒號(hào)后,會(huì)從命令行該選項(xiàng)后讀取該值。若該值存在,那么將被存在一個(gè)特殊的變量OPTARG中。如果該值不存在,getopts命令將在OPTARG中存放一個(gè)問(wèn)號(hào),并且在標(biāo)準(zhǔn)錯(cuò)誤輸出上顯示一條消息。

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

#--拷貝程序

COPIES=1 VERBOSE=N while getopts vc:OPTION do case $OPTION in c)COPIES=$OPTARG v)VERBOSE=Y ?)echo '無(wú)效參數(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

結(jié)果提示符號(hào)變成/usr/ice666>了嗎?沒(méi)有,為什么?

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

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

然后我們?cè)?profile文件中加入下面語(yǔ)句

.ice_ps

然后在切換目錄的時(shí)候,我們用chdir命令,結(jié)果是什么呢,自己實(shí)驗(yàn)好了!   調(diào)試Shell程序

1>調(diào)試shell程序

用戶(hù)剛編寫(xiě)完Shell程序中,不可避免的會(huì)有錯(cuò)誤,這時(shí)我們可以利用Bsh中提供的跟蹤選項(xiàng),該選項(xiàng)會(huì)顯示剛剛執(zhí)行的命令及參數(shù)。用戶(hù)可以通過(guò)set命令打開(kāi)-x選項(xiàng)或在啟動(dòng)Shell使用-x選項(xiàng)將Shell設(shè)置成跟蹤模式。例如有下面代碼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

我們用跟蹤模式運(yùn)行:

$sh -x ice_tx 2 3 4 結(jié)果顯示: +[ 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等沒(méi)顯示。 2>命令分組

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

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

3>使用Shell分層管理器shl

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

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

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

layers [-l] name  對(duì)于表中的每個(gè)層次,顯示其正在運(yùn)行的進(jìn)程的進(jìn)程號(hào),-l選項(xiàng)要求顯示詳細(xì)信息。

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

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

標(biāo)簽: Unix系統(tǒng)
主站蜘蛛池模板: 久久夜视频 | 日本免费一区二区三区 | 亚洲精品在线视频 | 国产一二三区精品视频 | 日韩在线免费视频 | 午夜免费精品视频 | 人人看人人搞 | 激情小说综合网 | 中文字幕一区在线 | 精品日韩在线 | 久久久久久久香蕉 | 欧美精品一二三 | 国产中文 | 黄色毛片一级 | 一区二区三区四区国产 | av在线伊人| 成人高清在线 | 日韩免费视频一区二区 | 中文字幕乱码视频32 | 欧美精品久久久久 | 91视频一区二区 | 天天搞天天操 | 一区免费| 狠狠热视频 | 91av视频在线| 在线视频一区二区 | 久久99精品视频 | 中文字幕在线免费观看 | 久久精品国产亚洲 | 国产精品成人久久久久a级 久久蜜桃av一区二区天堂 | 成人在线精品视频 | 国产精品久久久久久久久久久久 | 欧美一级特黄aaa大片在线观看 | 中文字幕乱码视频32 | 午夜精品一区二区三区在线观看 | 本道综合精品 | 国产成人啪免费观看软件 | 成人午夜精品一区二区三区 | 毛片站 | 午夜精品久久久久久久久久久久 | 狠狠骚 |