如何在 Linux 中使用雙括號條件測試

已發表: 2022-01-29
fatmawati achmad zaenuri/Shutterstock.com

條件測試根據邏輯表達式的結果對 Linux Bash 腳本的執行流程進行分支。 雙括號條件測試大大簡化了語法——但仍然有自己的陷阱。

單括號和雙括號

Bash 提供了test命令。 這使您可以測試邏輯表達式。 該表達式將返回一個表示真或假響應的答案。 返回值為零表示真正的響應。 零以外的任何值都表示錯誤。

使用&&運算符在命令行上鍊接命令使用此功能。 僅當前一個命令成功完成時才會執行命令。

如果測試為真,將打印“是”字樣。

 測試 15 -eq 15 && 回顯“是”
 測試 14 -eq 15 && 回顯“是” 

Bash 測試命令的簡單示例

單括號條件測試模仿test命令。 它們將表達式括在括號“ [ ] ”中,並像test命令一樣操作。 事實上,它們是相同的程序,由相同的源代碼創建。 唯一的操作差異是test版本和[版本如何處理幫助請求。

這是來自源代碼:

 /* 識別 --help 或 --version,但僅當在
"[" 形式,當最後一個參數不是 "]" 時。 直接使用
解析,而不是 parse_long_options,以避免接受
縮寫。 POSIX 允許 "[ --help" 和 "[ --version"
具有通常的 GNU 行為,但它需要“test --help”
和 "test --version" 以狀態 0 靜默退出。 */
廣告

我們可以通過向test[尋求幫助並檢查發送到 Bash 的響應代碼來查看其效果。

 測試——幫助
迴聲$?
 [  - 幫助
迴聲$? 

使用 --help 進行測試和 [

test[都是 shell builtins ,這意味著它們直接被烘焙到 Bash 中。 但也有一個獨立的二進製版本[

 型式試驗
類型 [
 哪裡 [ 

查找不同類型的 [ 和測試命令

相比之下,雙括號條件測試[[]]關鍵字[[]]也執行邏輯測試,但它們的語法不同。 因為它們是關鍵字,所以您可以使用一些在單括號版本中無法使用的簡潔功能。

Bash 支持雙括號關鍵字,但它們並非在所有其他 shell 中都可用。 例如,Korn shell 確實支持它們,但普通的舊 shell sh 不支持。 我們所有的腳本都以以下行開頭:

 #!/bin/bash

這確保我們調用 Bash shell 來運行腳本。

相關:如何在 Windows 10 上創建和運行 Bash Shell 腳本

內置函數和關鍵字

我們可以使用compgen程序列出內置函數:

 補償-b | fmt -w 70
廣告

如果不通過fmt管道輸出,我們會得到一個很長的列表,每個內置函數都在自己的行上。 在這種情況下,將內置函​​數組合成一個段落會更方便。

列出 Bash 內置函數

我們可以在列表中看到test[ ,但]沒有列出。 [命令查找結束]以檢測它何時到達表達式的末尾,但]不是單獨的內置命令。 這只是我們給[的一個信號,表示參數列表的結束。

要查看關鍵字,我們可以使用:

 補償-k | fmt -w 70 

列出 Bash 關鍵字

[[]]關鍵字都在列表中,因為[[是一個關鍵字,而]]是另一個關鍵字。 它們是一對,就像iffi以及caseesac一樣。

當 Bash 解析腳本或命令行並檢測到具有匹配的關閉關鍵字的關鍵字時,它會收集出現在它們之間的所有內容並應用關鍵字支持的任何特殊處理。

使用內建命令,內建命令後面的內容會像傳遞給任何其他命令行程序的參數一樣傳遞給它。 這意味著腳本的作者必須特別注意變量值中的空格等內容。

殼牌通配符

雙括號條件測試可以使用 shell globbing。 這意味著星號“ * ”將擴展為表示“任何東西”。

廣告

在編輯器中鍵入或複制以下文本並將其保存到名為“whelkie.sh”的文件中。

 #!/bin/bash

stringvar="惠爾基布魯克斯"

如果 [[ "$stringvar" == *elk* ]];
然後
  echo "警告包含海鮮"
別的
  echo "不含軟體動物"
菲

要使腳本可執行,我們需要使用帶有-x (執行)選項的chmod命令。 如果您想試用它們,您需要對本文中的所有腳本執行此操作。

 chmod +x whelkie.sh 

使用 chmod 使腳本可執行

當我們運行腳​​本時,我們看到在字符串“Whelkie”中找到了字符串“elk”,而不管它周圍有什麼其他字符。

 ./whelkie.sh 

運行 whelkie.sh 腳本

需要注意的一點是,我們不會將搜索字符串用雙引號括起來。 如果這樣做,則不會發生 globbing。 搜索字符串將按字面意思處理。

允許使用其他形式的 shell globbing。 問號“ ? ” 將匹配單個字符,單個方括號用於表示字符範圍。 例如,如果您不知道使用哪種情況,您可以用一個範圍涵蓋這兩種可能性。

 #!/bin/bash

stringvar="讓-克勞德·範·克拉姆"

如果 [[ "$stringvar" == *[cC]lam* ]];
然後
  echo "警告包含海鮮。"
別的
  echo "不含軟體動物。"
菲

將此腳本另存為“damme.sh”並使其可執行。 當我們運行它時,條件語句解析為真,並且執行 if 語句的第一個子句。

 ./damme.sh 

運行 damme.sh 腳本

引用字符串

我們之前提到過用雙引號括起來的字符串。 如果你這樣做,shell globbing 將不會發生。 儘管約定說這是一種很好的做法,但在使用[[]]時,即使字符串變量包含空格,也不需要將它們括在引號中。 看下一個例子。 $stringvar$surname字符串變量都包含空格,但在條件語句中都沒有引用。

 #!/bin/bash

stringvar="範達姆"
姓氏="範達姆"

如果 [[ $stringvar == $surname ]];
然後
echo "姓氏匹配。"
別的
echo "姓氏不匹配。"
菲
廣告

將其保存到名為“surname.sh”的文件中並使其可執行。 使用以下命令運行它:

 ./surname.sh 

運行 surname.sh 腳本

儘管兩個字符串都包含空格,但腳本成功並且條件語句解析為 true。 這在處理包含空格的路徑和目錄名稱時很有用。 在這裡,如果變量包含有效的目錄名稱,則-d選項返回 true。

 #!/bin/bash

dir="/home/dave/Documents/需要工作"

如果 [[ -d ${dir} ]];
然後
  echo "目錄已確認"
別的
  echo "找不到目錄"
菲

如果您更改腳本中的路徑以反映您自己計算機上的目錄,將文本保存到名為“dir.sh”的文件中並使其可執行,您可以看到這是可行的。

 ./dir.sh 

運行 dir.sh 腳本

相關:如何在 Bash 中使用變量

文件名通配問題

[ ][[ ]]之間的一個有趣區別與包含通配符的文件名有關。 “*.sh”形式將匹配所有腳本文件。 除非只有一個腳本文件,否則使用單括號[ ]會失敗。 查找多個腳本會引發錯誤。

這是帶有單括號條件的腳本。

 #!/bin/bash

如果 [ -a *.sh ];
然後
  echo "找到一個腳本文件"
別的
  echo "沒有找到腳本文件"
菲

我們將此文本保存到“script.sh”並使其可執行。 我們檢查了目錄中有多少腳本,然後運行腳本。

 ls
 ./script.sh 

運行 script.sh 腳本

廣告

Bash 拋出一個錯誤。 我們刪除了除一個腳本文件之外的所有文件並再次運行該腳本。

 ls
 ./script.sh 

使用目錄中的單個腳本運行 script.sh 腳本

條件測試返回 true 並且腳本不會導致錯誤。 編輯腳本以使用雙括號提供了第三種行為。

 #!/bin/bash

如果 [[ -a *.sh ]];
然後
  echo "找到一個腳本文件"
別的
  echo "沒有找到腳本文件"
菲

我們將其保存到一個名為“dscript.sh”的文件中並使其可執行。 在包含許多腳本的目錄中運行此腳本不會引發錯誤,但該腳本無法識別任何腳本文件。

使用雙括號的條件語句僅在您在目錄中有一個實際名為“*.sh”的文件的不太可能的情況下解析為 true。

 ./dscript.sh 

運行 dscript.sh 腳本

邏輯與和或

雙括號讓您可以使用&&|| 作為邏輯 AND 和 OR 運算符。

此腳本應將條件語句解析為 true,因為 10 確實等於 10 ,而25 小於 26。

 #!/bin/bash

第一個=10
秒=25

如果 [[ 第一個 -eq 10 && 第二個 -lt 26 ]];
然後
  echo "條件滿足"
別的
  echo "條件失敗"
菲
廣告

將此文本保存到名為“and.sh”的文件中,使其可執行,然後使用以下命令運行它:

 ./and.sh 

運行 and.sh 腳本

腳本按照我們的預期執行。

這次我們將使用|| 操作員。 條件語句應該解析為真,因為雖然 10 不大於 15,但 25 仍然小於 26。只要第一次比較第二次比較為真,條件語句作為一個整體解析為真。

將此文本保存為“or.sh”並使其可執行。

 #!/bin/bash

第一個=10
秒=25

如果 [[ 第一個 -gt 15 || 第二-lt 26]];
然後
  echo "條件滿足。"
別的
  echo "條件失敗。"
菲
./或.sh 

運行 or.sh 腳本

正則表達式

雙括號條件語句允許使用=~運算符,它將字符串中的正則表達式搜索模式應用於語句的另一半。 如果滿足正則表達式,則認為條件語句為真。 如果正則表達式找不到匹配項,則條件語句解析為 false。

相關:如何在 Linux 上使用正則表達式(regexes)

將此文本保存到名為“regex.sh”的文件中,並使其可執行。

 #!/bin/bash

話=“一二三”
WordsandNumbers="一 1 二 2 三 3"
email="[email protected]"

掩碼 1="[0-9]"
mask2="[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}"

如果 [[ $words =~ $mask1 ]];
然後
  echo "\"$words\" 包含數字。"
別的
  echo "在 \"$words\" 中找不到數字。"
菲

如果 [[ $WordsandNumbers =~ $mask1 ]];
然後
  echo "\"$WordsandNumbers\" 包含數字。"
別的
  echo "在 \"$WordsandNumbers\" 中找不到數字。"
菲

如果 [[ $email =~ $mask2 ]];
然後
  echo "\"$email\" 是一個有效的電子郵件地址。"
別的
  echo "無法解析 \"$email\"。"
菲

第一組雙括號使用字符串變量$mask1作為正則表達式。 這包含零到九範圍內所有數字的模式。 它將這個正則表達式應用於$words字符串變量。

第二組雙括號再次使用字符串變量$mask1作為正則表達式,但這次它與$WordsandNumbers字符串變量一起使用。

廣告

最後一組雙括號在字符串變量$mask2中使用了更複雜的正則表達式掩碼。

  • [A-Za-z0-9._%+-]+ :匹配任何大寫或小寫字母,或從零到九的任何數字,或句點、下劃線、百分號或加號或減號. “ [] ”之外的“ + ”表示重複這些匹配以找到盡可能多的字符。
  • @ :這僅匹配“@”字符。
  • [A-Za-z0-9.-]+ :這匹配任何大寫或小寫字母,或從零到九的任何數字,或句點或連字符。 “ [ ] ”之外的“ + ”表示對找到的字符重複這些匹配。
  • . : 這匹配“.” 僅字符。
  • [A-Za-z]{2,4} :匹配任何大寫或小寫字母。 “ {2,4} ”表示至少匹配兩個字符,最多匹配四個。

綜上所述,正則表達式掩碼將檢查電子郵件地址的格式是否正確。

將腳本文本保存到名為“regex.sh”的文件中並使其可執行。 當我們運行腳​​本時,我們會得到這個輸出。

 ./regex.sh 

運行 regex.sh 腳本

第一個條件語句失敗,因為正則表達式正在查找數字,但$words字符串變量中保存的值中沒有數字。

第二個條件語句成功,因為$WordsandNumbers字符串變量確實包含數字。

廣告

最後的條件語句成功了——也就是說,它解析為真——因為電子郵件地址的格式正確。

只有一個條件

雙括號條件測試為您的腳本帶來了靈活性和易讀性。 只要能夠在條件測試中使用正則表達式就可以證明學習如何使用[[]]

只需確保腳本調用支持它們的 shell,例如 Bash。

相關:你需要知道的 15 個特殊字符