加入星計劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴散
  • 作品版權(quán)保護
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
    • 1Tcl
    • 2Perl
    • 3Shell
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

IC腳本之條件控制 | 從Shell到Tcl到Perl

2023/01/02
3357
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

1Tcl

控制結(jié)構(gòu)允許程序根據(jù)不同的狀態(tài)、條件和參數(shù)來選擇不同的處理和執(zhí)行路徑,從而使代碼具有更強的靈活性、健壯性和可讀性。

Tcl?提供了?if、if/else、if/elseif、foreach、?for、while?和?switc等命令來管理控制結(jié)構(gòu)。這些命令和其他語言如C語言的條件語句的作用相同。需要區(qū)別的是在?Tcl?中所有控制結(jié)構(gòu)都是由相應(yīng)的命令來實現(xiàn),而?C?語言中則是一條控制語句。控制結(jié)構(gòu)通常要求帶有一個延遲執(zhí)行命令體或者過程體,這個命令體需要用花括號括起來以加以界定。

1.1if/else 命令

if?命令根據(jù)表達式的結(jié)果來執(zhí)行命令體:如果表達式結(jié)果為真,則執(zhí)行命令體,否則會執(zhí)行另外一個條件命令體(如果存在的話)。后面兩個命令體(elseif?和?else)是可選的。

[語法]?if { test expr?測試表達式?}?{

body 1

}?elseif {test expr?測試表達式}? {

body2

} else {

test expr

}

1.語法中用以界定過程體的花括號一定要和?if?命令在同一行上!因為對?Tcl?來講,換行符就是命令結(jié)束符,所以如果在?if?表達式后直接換行,寫成:

if { test expr }

{

...

}

就會出錯。Tcl?遇到換行后就認為命令結(jié)束,但找不到執(zhí)行命令體,返回錯誤。其他的控制命令,還有以后的過程定義命令等等都存在這個問題。

但情況并不全部如此。當在一個花括號體內(nèi)或者一個雙引號體內(nèi)換行的時候,解釋器不認為是命令的結(jié)束,所以上面的語法中,我們只將執(zhí)行命令體的第一個花括號(左括號)留在了?if?命令行和?else?命令行,然后另起一行書寫執(zhí)行命令體的過程語句,右括號也被單獨放到了一行上。這樣做是為了提高可讀性和便于查錯。

2.如果?if?后面還有?else/elseif?命令,則要留意?else/elseif?的位置。else/elseif?要跟在?if?執(zhí)行命令體的后面一個花括號后,不能分行,要有空格間隔花括號和?else /elseif。

3.花括號括起的表達式、執(zhí)行命令體或者其他內(nèi)容相當于變量存在,所以前后與其他命令元素之前要有空格,否則?Tcl?會返回語法錯誤。

4.可以使用多個?elseif?來創(chuàng)建一連串的條件命令控制結(jié)構(gòu)。

5.表達式支持變量替換和命令替換。

6.表達式的計算結(jié)果如果是”true”、”yes”和非零值就判斷為真,如果結(jié)果

是”false”、”no”和零則判斷為假??刂泼罡鶕?jù)表達式結(jié)果來判斷是否執(zhí)行相應(yīng)的執(zhí)行命令體。

1.2for命令

for?命令和?C?語言的?for?語句相似。for?命令的語法格式為:

[語法]:for {start} {test expr} {next} {body?

}

for?命令有四個變元,start?是預置條件或者初始化命令,告訴?for?命令起始執(zhí)行條件。test

expr?是條件布爾表達式,以決定是否執(zhí)行循環(huán)體?body,如果是真,則執(zhí)行循環(huán)體,如果假則退出命令。如果表達式真,則在執(zhí)行循環(huán)體后處理?next?命令,即?next?是一個后置命令執(zhí)行體。前三個變元可以選擇置空,而將相應(yīng)的處理放到循環(huán)體?body?中去。

1.3while命令

while?命令格式為:

[語法]:while {test?} {

body

}

while?命令和?for?命令非常相似。只要?test?為真,while?就執(zhí)行循環(huán)體直到?test?變?yōu)榧?。for命令和?while?命令的主要區(qū)別是,在?while?循環(huán)體內(nèi)你必須更改被檢測的測試體?test?的值,否則如果值一直沒有改變成假時,while?將無限的執(zhí)行循環(huán)體。而?for?命令你可以將這種處理過程在?next?變元中顯式給出。

1.4switch 命令

switch?命令通過將給定字符串與不同的匹配模式進行匹配從而選擇執(zhí)行多分支命令體。

switch?可基于模式匹配。命令格式為:

[語法]: switch [option]?string?{

pattern-1?{body1}

pattern-2?{body2}

pattern-n?{bodyn}

}

說明:

1.option?主要有:

-exact??用精確匹配(默認);

-glob ?????? ????? ?用?glob?格式行模式匹配;?-regexp???用?正則表達式模式匹配;?--????????????標記選項結(jié)束或者說明不用選項。

1.5eval命令

用于創(chuàng)建和運行tcl腳本的通用構(gòu)造塊。它接受任一多個參數(shù),把它們用分隔符串接起來,然后把串接的結(jié)果作為一個tcl腳本處理。

set reset {

set a 0

set b 0

set c 0

}

...

eval $reset

又如:

set vars {a b c d}

eval unset $vars

串接?unset $vars?參數(shù)后結(jié)果為

unset {a b c d}

然后把以上語句作為一個tcl腳本執(zhí)行,結(jié)果清除a b c d四個變量。

1.6source和return命令

讀取一個文件,將其內(nèi)容作為tcl腳本運行。一個參數(shù),該參數(shù)指定要讀取的文件名。例如:

source init.tcl改命令運行init.tcl文件的內(nèi)容??梢杂媒^對路徑或相對路徑。source的返回值就是文件內(nèi)容的返回值,即文件中最后一個命令的返回值。另外source允許在文件內(nèi)的腳本中使用return命令終止過程。使用source命令,可以將一個大的腳本分為小的模塊,又一個主腳本用source調(diào)用其他的腳本模塊??梢酝ㄟ^把過程定義放到一個文件中,把可重用的過程建立成庫。

1.7break和continue命令

break?命令可以用來無條件停止并跳出循環(huán);continue 命令可以用來結(jié)束目前這一輪的循環(huán),直接跳到下一輪循環(huán)。

2Perl

2.1布爾值判斷

如果是數(shù)字,0表示假,其它所有數(shù)字都是真。

如果是字符串,空字符串('')為假,其它所有字符串為真(有例外,見下一條)。

如果是字符串'0',perl是當作數(shù)值0來處理的,所以這是唯一的非空但為假的字符串。

如果既不是數(shù)字,也不是字符串,那么先轉(zhuǎn)換為數(shù)字或字符串再做判斷(也就是"undef"表示假,其它所有引用表示真)。

"!"表示取反。

perl有個技巧,將兩個"!"一起用,相當于"負負得正",所以原來是真的仍然是真的,原來是假的仍然是假的。但實際上,perl會將它們轉(zhuǎn)換值"1"和"undef"。

2.2條件判斷if和unless

它們都是條件判斷語句,都支持else、elsif子句。

其中CONDITION可以是任意一個標量值。布爾值的判斷很簡單,方式和bash shell有點類似,但有點相反。unless和if判斷方式相反,if的condition為真則執(zhí)行后面的代碼,否則執(zhí)行else或者退出if結(jié)構(gòu)。unless則是condition為假時才執(zhí)行后面的代碼,否則執(zhí)行else或退出unless結(jié)構(gòu)。所以,unless相當于if的else部分,或者相當于if (!condition)。一般來說,不會用到unless的else語句,因為它完全可以改編成if語句。之所以有時候會使用unless而不是if的否定形式,是因為有時候的條件語句用if來寫確實不方便。

2.3三目運算符

perl也支持三目運算符:如果expression返回真,則整個表達式返回if_true,否則返回if_false。

例如,求平均值,如果$n=0,則輸出"------"。

它等價于:

三目運算符可以寫出更復雜的分支:

執(zhí)行結(jié)果:

2.4邏輯運算符and(&&)、or(||)、not(!)

&&運算符只有兩邊為真時才返回真,且短路計算:expr1為假時直接返回false,不會評估expr2。||運算符只要一邊為真時就返回真,且短路計算:expr1為真時直接返回true,不會評估expr2。and和or基本等價于對應(yīng)的&&和||,但文字格式的邏輯運算符優(yōu)先級非常低。not和!求反,同樣文字格式的not的優(yōu)先級很低。因為符號格式的邏輯運算符優(yōu)先級很高,所以往往左邊和右邊都會加上括號,而文字格式的優(yōu)先級很低,左右兩邊不需加括號。

or運算符往往用于連接兩個"成功執(zhí)行,否則就"的子句。例如,打開文件,如果打開失敗,就結(jié)束該perl程序:

更常見的,還會分行縮進:

同樣,and運算符也常用于連接兩個行為:左邊為真,就執(zhí)行右邊的操作(例如賦值)。

以下是3個語句是等價語句:

2.5while和until循環(huán)


until和其它某些語言的until循環(huán)有所不同,perl的until循環(huán),內(nèi)部的commands主體可能一次也不會執(zhí)行,因為Perl會先進行條件判斷,當條件為假時就執(zhí)行,如果第一次判斷就為真,則直接退出until。

2.6for循環(huán)

Perl中的for循環(huán)采取C語言的for風格,例如:

需要注意的是,上面的$i默認是全局變量,循環(huán)結(jié)束后還有效??梢允褂胢y關(guān)鍵字將其聲明為局部變量:

for循環(huán)不僅僅只支持數(shù)值遞增、遞減的循環(huán)方式,還支持其它類型的循環(huán),只要能進行判斷即可。見下面的例子。

for關(guān)鍵字后面括號中的3個表達式都可以省略,但兩個分號不能省略:

如果省略第三個表達式,則表示一直判斷,直到退出循環(huán)或者無限循環(huán)。如果省略第二個表達式,則表示不判斷,所以會無限循環(huán)。如果省略第一個表達式,則表示不做初始賦值。例如,下面分別省略第三個表達式和省略所有表達式:

對于無限循環(huán),Perl中更好更優(yōu)化的方式是使用:

Perl中的for也支持成員測試性的遍歷,就像shell中的for i in ...的操作一樣,它期待一個列表上下文,表示遍歷整個列表。如果省略控制變量,表示使用$_。例如:

像for遍歷列表元素的操作,可以使用foreach來替代,大多數(shù)迭代列表的時候它們可以互換。

2.7foreach循環(huán)

foreach更適合用于遍歷,所有foreach都能直接修改關(guān)鍵字為for而轉(zhuǎn)換成for循環(huán)。當寫成for格式的時候,perl通過判斷括號中的分號來決定這是foreach循環(huán)還是for的普通循環(huán)。但for能實現(xiàn)的循環(huán)功能,foreach不一定能實現(xiàn),因為for中有初始變量,有條件判斷,而foreach則是簡單版的for循環(huán)。

先解釋下foreach的用法:

例如,迭代從1到10的列表:

其中$i稱為控制變量,每迭代一次都會從迭代列表中取出一個元素賦值給控制變量??梢允÷钥刂谱兞?,這時將采用默認的變量$_:

foreach可以改寫為for:


關(guān)于for循環(huán)和foreach循環(huán),如果在遍歷過程中修改了元素的值,它會直接修改原始值。換句話說,迭代時賦值給控制變量的元素的引用,而不是賦值元素再賦值給控制變量。

當foreach/for遍歷結(jié)束后,控制變量將復原為foreach/for遍歷前的值(例如未定義的是undef)。

 

2.8each

each用來遍歷hash或數(shù)組,每次迭代的過程中,都獲取hash的key和value,數(shù)組的index(數(shù)值,從0開始)和元素值。each放在列表上下文,會返回key/value或index/element,放在標量上下文則只返回key或index。

遍歷hash:

輸出結(jié)果:

遍歷數(shù)組:

輸出結(jié)果:

each放在標量上下文:

輸出結(jié)果:

2.9執(zhí)行一次的語句塊

使用大括號包圍一段語句,這些語句就屬于這個語句塊,這個語句塊其實是一個循環(huán)塊結(jié)構(gòu),只不過它只循環(huán)一次。語句塊也有自己的范圍,例如可以將變量定義為局部變量。

2.10循環(huán)控制last、next、redo、LABEL

last相當于其它語言里的break關(guān)鍵字,用于退出當前循環(huán)塊(for/foreach/while/until/執(zhí)行一次的語句塊都屬于循環(huán)塊),注意是只退出當前層次的循環(huán),不會退出外層循環(huán)next相當于其它語言里的continue關(guān)鍵字,用于跳入下一次迭代。同樣只作用于當前層次的循環(huán)redo用于跳轉(zhuǎn)到當前循環(huán)層次的頂端,所以本次迭代中曾執(zhí)行過的語句可能會再次執(zhí)行標簽用于為循環(huán)塊打上標記,以便那些循環(huán)塊控制關(guān)鍵字(last/next/redo)可以指定操作的循環(huán)層次。

以下是打標簽的示例(標簽建議采用大寫):

上面的標簽循環(huán)中,首先讀取一行輸入,然后進入foreach遍歷,因為split沒有參數(shù),所以使用默認參數(shù)$_,這個$_所屬范圍是while循環(huán),split以空格作為分隔符分割這一行,同時foreach也沒有控制變量,所以使用默認的控制變量$_,這個$_所屬范圍是foreach循環(huán)。當foreach的$_能匹配字符串"error"則直接退出while循環(huán),而不僅僅是自己的foreach循環(huán)。這里if語句后采用的匹配目標是屬于foreach的默認變量$_。

例如,這個perl程序讀取a.txt文件,其中a.txt文件的內(nèi)容如下:

執(zhí)行這個perl程序:

可見,只輸出了a.txt中第二行Error前的4個單詞。

2.11附加循環(huán)continue

perl中還有一個continue關(guān)鍵字,它可以是一個函數(shù),也可以跟一個代碼塊。

如果指定了BLOCK,continue可用于while和foreach之后,表示附加在循環(huán)結(jié)構(gòu)上的代碼塊。

每次循環(huán)中都會執(zhí)行此代碼塊,執(zhí)行完后進入下一循環(huán)。

在continue代碼塊內(nèi)部,也可以使用redo、last和next控制關(guān)鍵字。所以,這幾個流程控制關(guān)鍵字更細致一點的作用是:redo、last直接控制循環(huán)主體,而next是控制continue代碼塊。所以:

實際上,while和foreach在沒有給定continue的時候,邏輯上等價于給了一個空的代碼塊,這時next可以跳轉(zhuǎn)到空代碼而進入下一輪循環(huán)。

例如:

輸出結(jié)果:

3Shell

和 Java、PHP 等語言不一樣,sh 的流程控制不可為空,如(以下為 PHP 流程控制寫法):

在 sh/bash 里可不能這么寫,如果 else 分支沒有語句執(zhí)行,就不要寫這個 else。

3.1if else

if 語句語法格式:

寫成一行(適用于終端命令提示符):

末尾的?fi?就是?if?倒過來拼寫。

3.2if else-if else

if else-if else 語法格式:

if else 的?[...]?判斷語句中大于使用?-gt,小于使用?-lt。

如果使用?((...))?作為判斷語句,大于和小于可以直接使用?>?和?<。

以下實例判斷兩個變量是否相等:

輸出結(jié)果:

使用?((...))?作為判斷語句:

輸出結(jié)果:

if else 語句經(jīng)常與 test 命令結(jié)合使用,如下所示:

輸出結(jié)果:

3.3for循環(huán)

與其他編程語言類似,Shell支持for循環(huán)。

for循環(huán)一般格式為:

寫成一行:

當變量值在列表里,for?循環(huán)即執(zhí)行一次所有命令,使用變量名獲取列表中的當前取值。命令可為任何有效的?shell?命令和語句。in?列表可以包含替換、字符串和文件名。in列表是可選的,如果不用它,for循環(huán)使用命令行的位置參數(shù)。例如,順序輸出當前列表中的數(shù)字:

輸出結(jié)果:

順序輸出字符串中的字符:

輸出結(jié)果:

3.4while 語句

while?循環(huán)用于不斷執(zhí)行一系列命令,也用于從輸入文件中讀取數(shù)據(jù)。其語法格式為:

以下是一個基本的?while?循環(huán),測試條件是:如果?int?小于等于?5,那么條件返回真。int?從?1?開始,每次循環(huán)處理時,int?加?1。運行上述腳本,返回數(shù)字?1?到?5,然后終止。

運行腳本,輸出:

while循環(huán)可用于讀取鍵盤信息。下面的例子中,輸入信息被設(shè)置為變量FILM,按結(jié)束循環(huán)。

3.5無限循環(huán)

無限循環(huán)語法格式:

或者

或者

3.6until 循環(huán)

until?循環(huán)執(zhí)行一系列命令直至條件為?true?時停止。until?循環(huán)與?while?循環(huán)在處理方式上剛好相反。一般?while?循環(huán)優(yōu)于?until?循環(huán),但在某些時候—也只是極少數(shù)情況下,until?循環(huán)更加有用。until?語法格式:

condition?一般為條件表達式,如果返回值為?false,則繼續(xù)執(zhí)行循環(huán)體內(nèi)的語句,否則跳出循環(huán)。

以下實例我們使用?until?命令來輸出?0 ~ 9?的數(shù)字:

運行結(jié)果:

輸出結(jié)果為:

3.7case ... esac

case ... esac?為多選擇語句,與其他語言中的?switch ... case?語句類似,是一種多分支選擇結(jié)構(gòu),每個?case?分支用右圓括號開始,用兩個分號?;;?表示?break,即執(zhí)行結(jié)束,跳出整個?case ... esac?語句,esac(就是?case?反過來)作為結(jié)束標記??梢杂?case?語句匹配一個值與一個模式,如果匹配成功,執(zhí)行相匹配的命令。case ... esac?語法格式如下:

case?工作方式如上所示,取值后面必須為單詞?in,每一模式必須以右括號結(jié)束。取值可以為變量或常數(shù),匹配發(fā)現(xiàn)取值符合某一模式后,其間所有命令開始執(zhí)行直至?;;。取值將檢測匹配的每一個模式。一旦模式匹配,則執(zhí)行完匹配模式相應(yīng)命令后不再繼續(xù)其他模式。如果無一匹配模式,使用星號?*?捕獲該值,再執(zhí)行后面的命令。下面的腳本提示輸入?1?到?4,與每一種模式進行匹配:

輸入不同的內(nèi)容,會有不同的結(jié)果,例如:

下面的腳本匹配字符串:

輸出結(jié)果為:

3.8跳出循環(huán)

在循環(huán)過程中,有時候需要在未達到循環(huán)結(jié)束條件時強制跳出循環(huán),Shell?使用兩個命令來實現(xiàn)該功能:break?和?continue。

break?命令允許跳出所有循環(huán)(終止執(zhí)行后面的所有循環(huán))。下面的例子中,腳本進入死循環(huán)直至用戶輸入數(shù)字大于5。要跳出這個循環(huán),返回到shell提示符下,需要使用break命令。

執(zhí)行以上代碼,輸出結(jié)果為:

continue?命令與?break?命令類似,只有一點差別,它不會跳出所有循環(huán),僅僅跳出當前循環(huán)。對上面的例子進行修改:

運行代碼發(fā)現(xiàn),當輸入大于5的數(shù)字時,該例中的循環(huán)不會結(jié)束,語句?echo "游戲結(jié)束"?永遠不會被執(zhí)行

參考文獻

https://www.runoob.com/linux/linux-shell-process-control.html

https://www.junmajinlong.com/shell/script_course/shell_flow_control/

https://blog.csdn.net/J080624/article/details/107457247

https://www.cnblogs.com/kane1990/archive/2011/12/19/2293978.html

https://blog.csdn.net/sinat_41774721/article/details/122928261

https://www.cnblogs.com/huguodong/p/5882597.html

https://www.cnblogs.com/f-ck-need-u/p/9511878.html

https://www.jc2182.com/perl/perl-workflow.html

https://blog.csdn.net/sunshoupo211/article/details/30747887

https://www.runoob.com/perl/perl-conditions.html

https://www.runoob.com/perl/perl-loops.html

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄