tft每日頭條

 > 生活

 > 結構方塊獲得命令

結構方塊獲得命令

生活 更新时间:2024-11-29 19:50:02
12.1 使用if-then語句

if-then語句有如下格式:

if command then commands fi

bash shell的if語句會運行if後面的那個命令。如果該命令的退出狀态碼(參見第11章)是0(該命令成功運行),位于then部分的命令就會被執行。如果該命令的退出狀态碼是其他值, then部分的命令就不會被執行,bash shell會繼續執行腳本中的下一個命令。fi語句用來表示if-then語句到此結束。

結構方塊獲得命令(使用結構化命令)1

結構方塊獲得命令(使用結構化命令)2

說明 你可能在有些腳本中看到過if-then語句的另一種形式:

if command; then

commands

fi

通過把分号放在待求值的命令尾部,就可以将then語句放在同一行上了,這樣看起來更像其他編程語言中的if-then語句。

12.2 if-then-else語句

if command then commands else commands fi

當if語句中的命令返回退出狀态碼0時,then部分中的命令會被執行,這跟普通的if-then語句一樣。當if語句中的命令返回非零退出狀态碼時,bash shell會執行else部分中的命令。

12.3 嵌套if

檢查腳本代碼中的多種條件

要檢查/etc/passwd文件中是否存在某個用戶名以及該用戶的目錄是否尚在,可以使用嵌套的if-then語句。嵌套的if-then語句位于主if-then-else語句的else代碼塊中。

結構方塊獲得命令(使用結構化命令)3

可以使用else部分的另一種形式:elif。這樣就不用再書寫多個if-then語句了。elif使用另一個if-then語句延續else部分。

if command1 then commands elif command2 then more commands fi

elif語句行提供了另一個要測試的命令,這類似于原始的if語句行。如果elif後命令的退出狀态碼是0,則bash會執行第二個then語句部分的命令。使用這種嵌套方法,代碼更清晰,邏輯更易懂

結構方塊獲得命令(使用結構化命令)4

在elif語句中,緊跟其後的else語句屬于elif代碼塊。它們并不屬于之前的if-then代碼塊

12.4 test命令

test命令提供了在if-then語句中測試不同條件的途徑。如果test命令中列出的條件成立,test命令就會退出并返回退出狀态碼0。這樣if-then語句就與其他編程語言中的if-then語句以類似的方式工作了。如果條件不成立,test命令就會退出并返回非零的退出狀态碼,這使得if-then語句不會再被執行。

test命令的格式非常簡單。

test condition

condition是test命令要測試的一系列參數和值。當用在if-then語句中時,test命令看起來是這樣的。

if test condition then commands fi

如果不寫test命令的condition部分,它會以非零的退出狀态碼退出,并執行else語句塊

結構方塊獲得命令(使用結構化命令)5

當你加入一個條件時,test命令會測試該條件。例如,可以使用test命令确定變量中是否有内容。這隻需要一個簡單的條件表達式。

結構方塊獲得命令(使用結構化命令)6

變量my_variable中包含有内容(Full),因此當test命令測試條件時,返回的退出狀态為0。這使得then語句塊中的語句得以執行。

如你所料,如果該變量中沒有包含内容,就會出現相反的情況。

結構方塊獲得命令(使用結構化命令)7

bash shell提供了另一種條件測試方法,無需在if-then語句中聲明test命令。

if [ condition ] then commands fi

方括号定義了測試條件。注意,第一個方括号之後和第二個方括号之前必須加上一個空格,否則就會報錯。

test命令可以判斷三類條件:

 數值比較

 字符串比較

 文件比較

12.4.1 數值比較

使用test命令最常見的情形是對兩個數值進行比較

結構方塊獲得命令(使用結構化命令)8

例子:

結構方塊獲得命令(使用結構化命令)9

第一個條件測試:

if [ $value1 -gt 5 ]

測試變量value1的值是否大于5。第二個條件測試:

if [ $value1 -eq $value2 ]

測試變量value1的值是否和變量value2的值相等。兩個數值條件測試的結果和預想一緻。

結構方塊獲得命令(使用結構化命令)10

涉及浮點值時,數值條件測試會有一個限制

結構方塊獲得命令(使用結構化命令)11

此例,變量value1中存儲的是浮點值。接着,腳本對這個值進行了測試。顯然這裡出錯了。

記住,bash shell隻能處理整數。如果你隻是要通過echo語句來顯示這個結果,那沒問題。但是,在基于數字的函數中就不行了,例如我們的數值測試條件。最後一行就說明我們不能在test命令中使用浮點值。

12.4.2 字符串比較

結構方塊獲得命令(使用結構化命令)12

1. 字符串相等性

結構方塊獲得命令(使用結構化命令)13

結構方塊獲得命令(使用結構化命令)14

記住,在比較字符串的相等性時,比較測試會将所有的标點和大小寫情況都考慮在内。

2. 字符串順序

要測試一個字符串是否比另一個字符串大就是麻煩的開始。當要開始使用測試條件的大于或小于功能時,就會出現兩個經常困擾shell程序員的問題:

大于号和小于号必須轉義,否則shell會把它們當作重定向符号,把字符串值當作文件名;

 大于和小于順序和sort命令所采用的不同。

結構方塊獲得命令(使用結構化命令)15

這個腳本中隻用了大于号,沒有出現錯誤,但結果是錯的。腳本把大于号解釋成了輸出重定向。因此,它創建了一個名為hockey的文件。由于重定向的順利完成,test命令返回了退出狀态碼0,if語句便以為所有命令都成功結束了。

要解決這個問題,就需要正确轉義大于号。

結構方塊獲得命令(使用結構化命令)16

第二個問題更細微,除非你經常處理大小寫字母,否則幾乎遇不到。sort命令處理大寫字母的方法剛好跟test命令相反。

結構方塊獲得命令(使用結構化命令)17

在比較測試中,大寫字母被認為是小于小寫字母的。但sort命令恰好相反。當你将同樣的字符串放進文件中并用sort命令排序時,小寫字母會先出現。這是由各個命令使用的排序技術不同造成的

比較測試中使用的是标準的ASCII順序,根據每個字符的ASCII數值來決定排序結果(字母A比字母Z要小,并按A到Z順序遞增。同個字母的大寫字母比小寫字母要小32)。

sort命令使用的是系統的本地化語言設置中定義的排序順序。對于英語,本地化設置指定了在排序順序中小寫字母出現在大寫字母前。

test命令和測試表達式使用标準的數學比較符号來表示字符串比較,而用文本代碼來表示數值比較。這個細微的特性被很多程序員理解反了。如果你對數值使用了數學運算符号,shell會将它們當成字符串值,可能無法得到正确的結果。

字符串比較用/> 數字比較用-gt

3. 字符串大小

-n和-z可以檢查一個變量是否含有數據。

結構方塊獲得命令(使用結構化命令)18

這個例子創建了兩個字符串變量。val1變量包含了一個字符串,val2變量包含的是一個空字符串。後續的比較如下:

if [ -n $val1 ] 判斷val1變量是否長度非0,而它的長度正好非0,所以then部分被執行了。

if [ -z $var2 ] 判斷val2變量是否長度為0,而它正好長度為0,所以then部分被執行了。

if [ -z $val3 ] 判斷val3變量是否長度為0。這個變量并未在shell腳本中定義過,所以它的字符串長度仍然為0,盡管它未被定義過。

空的和未初始化的變量會對shell腳本測試造成災難性的影響。如果不是很确定一個變量的内容,最好在将其用于數值或字符串比較之前先通過-n或-z來測試一下變量是否含有值。

12.4.3 文件比較

最後一類比較測試很有可能是shell編程中最為強大、也是用得最多的比較形式。它允許你測試Linux文件系統上文件和目錄的狀态

結構方塊獲得命令(使用結構化命令)19

1. 檢查目錄

-d測試會檢查指定的目錄是否存在于系統中。如果你打算将文件寫入目錄或是準備切換到某個目錄中,先進行測試總是件好事情。

結構方塊獲得命令(使用結構化命令)20

示例代碼中使用了-d測試條件來檢查jump_directory變量中的目錄是否存在:若存在,就使用cd命令切換到該目錄并列出目錄中的内容;若不存在,腳本就輸出一條警告信息,然後退出。

2. 檢查對象是否存在

-e比較允許你的腳本代碼在使用文件或目錄前先檢查它們是否存在。

結構方塊獲得命令(使用結構化命令)21

第一次檢查用-e比較來判斷用戶是否有$HOME目錄。如果有,接下來的-e比較會檢查sentinel文件是否存在于$HOME目錄中。如果不存在,shell腳本就會提示該文件不存在,不需要進行更新。

為确保更新操作能夠正常進行,我們創建了sentinel文件,然後重新運行這個shell腳本。這一次在進行條件測試時,$HOME和sentinel文件都存在,因此當前日期和時間就被追加到了文件中。

3. 檢查文件

-e比較可用于文件和目錄。要确定指定對象為文件,必須用-f比較。

結構方塊獲得命令(使用結構化命令)22

這一小段腳本進行了大量的檢查!它首先使用-e比較測試$HOME是否存在。如果存在,繼續用-f來測試它是不是一個文件。如果它不是文件(當然不會是了),就會顯示一條消息,表明這不是一個文件。

我們對變量item_name作了一個小小的修改,将目錄$HOME替換成文件$HOME/sentinel,結果就不一樣了。

結構方塊獲得命令(使用結構化命令)23

這裡隻列出了腳本test13.sh的部分代碼,因為隻改變了腳本變量item_name的值。當運行這個腳本時,對$HOME/sentinel進行的-f測試所返回的退出狀态碼為0,then語句得以執行,然後輸出消息:Yes, /home/Christine/sentinel is a file。

4. 檢查是否可讀

在嘗試從文件中讀取數據之前,最好先測試一下文件是否可讀。可以使用-r比較測試。

結構方塊獲得命令(使用結構化命令)24

/etc/shadow文件含有系統用戶加密後的密碼,所以它對系統上的普通用戶來說是不可讀的。-r比較确定該文件不允許進行讀取,因此測試失敗,bash shell執行了if-then語句的else部分。

5. 檢查空文件

應該用-s比較來檢查文件是否為空,尤其是在不想删除非空文件的時候。要留心的是,當-s比較成功時,說明文件中有數據

結構方塊獲得命令(使用結構化命令)25

-f比較測試首先測試文件是否存在。如果存在,由-s比較來判斷該文件是否為空。空文件會被删除。可以從ls –l的輸出中看出sentinel并不是空文件,因此腳本并不會删除它。

6. 檢查是否可寫

-w比較會判斷你對文件是否有可寫權限。腳本test16.sh隻是腳本test13.sh的修改版。現在不單檢查item_name是否存在、是否為文件,還會檢查該文件是否有寫入權限。

結構方塊獲得命令(使用結構化命令)26

變量item_name被設置成$HOME/sentinel,該文件允許用戶進行寫入。因此當腳本運行時,-w測試表達式會返回零退出狀态,然後執行then代碼塊,将時間戳寫入文件sentinel中。

如果使用chmod關閉文件sentinel的用戶 寫入權限,-w測試表達式會返回非零的退出狀态碼,時間戳不會被寫入文件。

7. 檢查文件是否可以執行

-x比較是判斷特定文件是否有執行權限的一個簡單方法。雖然可能大多數命令用不到它,但如果你要在shell腳本中運行大量腳本,它就能發揮作用。

結構方塊獲得命令(使用結構化命令)27

這段示例shell腳本用-x比較來測試是否有權限執行test16.sh腳本。如果有權限,它會運行這個腳本。在首次成功運行test16.sh腳本後,更改文件的權限。這次,-x比較失敗了,因為你已經沒有test16.sh腳本的執行權限了。

8. 檢查所屬關系

-O比較可以測試出你是否是文件的屬主。

結構方塊獲得命令(使用結構化命令)28

這段腳本用-O比較來測試運行該腳本的用戶是否是/etc/passwd文件的屬主。這個腳本是運行在普通用戶賬戶下的,所以測試失敗了。

9. 檢查默認屬組關系

-G比較會檢查文件的默認組,如果它匹配了用戶的默認組,則測試成功。由于-G比較隻會檢查默認組而非用戶所屬的所有組,這會叫人有點困惑。這裡有個例子。

結構方塊獲得命令(使用結構化命令)29

第一次運行腳本時,$HOME/testing文件屬于rich組,所以通過了-G比較。接下來,組被改成了sharing組,用戶也是其中的一員。但是,-G比較失敗了,因為它隻比較默認組,不會去比較其他的組。

10. 檢查文件日期

最後一組方法用來對兩個文件的創建日期進行比較。

-nt比較會判定一個文件是否比另一個文件新。如果文件較新,那意味着它的文件創建日期更近。

-ot比較會判定一個文件是否比另一個文件舊。如果文件較舊,意味着它的創建日期更早。

結構方塊獲得命令(使用結構化命令)30

用于比較文件路徑是相對你運行該腳本的目錄而言的。如果你要檢查的文件已經移走,就會出現問題。另一個問題是,這些比較都不會先檢查文件是否存在

結構方塊獲得命令(使用結構化命令)31

這個小例子演示了如果文件不存在,-nt比較會返回一個錯誤的結果。在你嘗試使用-nt或-ot比較文件之前,必須先确認文件是存在的。

12.5 複合條件測試

if-then語句允許你使用布爾邏輯來組合測試。有兩種布爾運算符可用:

 [ condition1 ] && [ condition2 ]

 [ condition1 ] || [ condition2 ]

第一種布爾運算使用AND布爾運算符來組合兩個條件。要讓then部分的命令執行,兩個條件都必須滿足。

第二種布爾運算使用OR布爾運算符來組合兩個條件。如果任意條件為TRUE,then部分的命令就會執行。

布爾邏輯是一種能夠将可能的返回值簡化為TRUE或FALSE的方法。

結構方塊獲得命令(使用結構化命令)32

使用AND布爾運算符時,兩個比較都必須滿足。第一個比較會檢查用戶的$HOME目錄是否存在。第二個比較會檢查在用戶的$HOME目錄是否有個叫testing的文件,以及用戶是否有該文件的寫入權限。如果兩個比較中的一個失敗了,if語句就會失敗,shell就會執行else部分的命令。如果兩個比較都通過了,則if語句通過,shell會執行then部分的命令。

12.6 if-then的高級特性

bash shell提供了兩項可在if-then語句中使用的高級特性:

 用于數學表達式的雙括号

 用于高級字符串處理功能的雙方括号

12.6.1 使用雙括号 (數學表達式)

雙括号命令允許你在比較過程中使用高級數學表達式。test命令隻能在比較中使用簡單的算術操作。雙括号命令提供了更多的數學符号,這些符号對于用過其他編程語言的程序員而言并不陌生。雙括号命令的格式如下:

(( expression ))

expression可以是任意的數學賦值或比較表達式。除了test命令使用的标準數學運算符,表12-4列出了雙括号命令中會用到的其他運算符。

結構方塊獲得命令(使用結構化命令)33

可以在if語句中用雙括号命令,也可以在腳本中的普通命令裡使用來賦值。

結構方塊獲得命令(使用結構化命令)34

注意,不需要将雙括号中表達式裡的大于号轉義。這是雙括号命令提供的另一個高級特性。

12.6.2 使用雙方括号(字符串比較)

雙方括号命令提供了針對字符串比較的高級特性。雙方括号命令的格式如下:

[[ expression ]]

雙方括号裡的expression使用了test命令中采用的标準字符串比較。但它提供了test命令未提供的另一個特性——模式匹配(pattern matching)。

雙方括号在bash shell中工作良好。不過要小心,不是所有的shell都支持雙方括号。

在模式匹配中,可以定義一個正則表達式來匹配字符串值。

結構方塊獲得命令(使用結構化命令)35

在上面的腳本中,我們使用了雙等号(==)。雙等号将右邊的字符串(r*)視為一個模式,并應用模式匹配規則。雙方括号命令$USER環境變量進行匹配,看它是否以字母r開頭。如果是的話,比較通過,shell會執行then部分的命令。

12.7 case命令

有了case命令,就不需要再寫出所有的elif語句來不停地檢查同一個變量的值了。case命令會采用列表格式來檢查單個變量的多個值

case variable in pattern1 | pattern2) commands1;; pattern3) commands2;; *) default commands;; esac

case命令會将指定的變量與不同模式進行比較。如果變量和模式是匹配的,那麼shell會執行為該模式指定的命令。可以通過豎線操作符在一行中分隔出多個模式模式。星号會捕獲所有與已知模式不匹配的值。

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved