https://www.cnblogs.com/liuyuelinfighting/p/16377705.html
在 Shell 腳本中,&&
和 ||
是邏輯操作符,用于根據前一個命令的退出狀態(成功或失敗)決定是否執行后續命令。這種語法稱為 命令鏈(Command Chaining)。
語法解析
[ -d student.txt ] && echo yes || echo no
-
[ -d student.txt ]
- 這是一個條件測試命令,用于檢查
student.txt
是否是一個目錄(-d
參數)。 - 如果目錄存在,返回退出狀態
0
(成功);否則返回非0
(失敗)。
- 這是一個條件測試命令,用于檢查
-
&&
(邏輯與)- 僅當左側命令成功時(退出狀態為
0
),才會執行右側的命令。 - 示例:
若目錄存在,則執行[ -d student.txt ] && echo yes
echo yes
;若不存在,跳過echo yes
。
- 僅當左側命令成功時(退出狀態為
-
||
(邏輯或)- 僅當左側命令失敗時(退出狀態非
0
),才會執行右側的命令。 - 示例:
若目錄不存在,則執行[ -d student.txt ] || echo no
echo no
;若存在,跳過echo no
。
- 僅當左側命令失敗時(退出狀態非
組合效果
-
目錄存在時:
[ -d student.txt ]
成功 → 執行&&
后的echo yes
→echo yes
成功 → 跳過||
后的echo no
。
輸出:yes
-
目錄不存在時:
[ -d student.txt ]
失敗 → 跳過&&
后的echo yes
→ 由于左側整體失敗,執行||
后的echo no
。
輸出:no
等價于 if-else 語句
上述命令鏈等價于以下 if-else
結構:
if [ -d student.txt ]; thenecho yes
elseecho no
fi
注意事項
-
&&
和||
的優先級
&&
的優先級高于||
,因此命令按以下分組執行:
( [ -d student.txt ] && echo yes ) || echo no
-
命令退出狀態是關鍵
- 每個命令的退出狀態決定后續操作(
0
=成功,非0
=失敗)。 - 例如,若
echo yes
意外失敗(極罕見),也會觸發|| echo no
。
- 每個命令的退出狀態決定后續操作(
其他常見用法
# 1. 僅當命令成功時執行操作
rm file.txt && echo "刪除成功"# 2. 僅當命令失敗時執行操作
cp a.txt b.txt || echo "復制失敗"# 3. 復雜組合(注意括號分組)
make && ( echo "編譯成功"; ./app ) || echo "編譯失敗"
通過命令鏈可以簡潔地實現條件邏輯,但復雜的場景建議使用 if-else
增強可讀性。
在 Shell 腳本中,單層中括號 [ ]
和雙層中括號 [[ ]]
都是條件測試語法,但 [[ ]]
是 Bash 的增強版測試命令,提供了更強大、更安全的功能。以下是主要區別和優勢:
1. 避免變量擴展問題(更安全)
[[ ]]
會自動處理變量中的空格和特殊字符,不需要額外加引號:
file="my file.txt"# 單括號會報錯(解析成 [ -f my file.txt ])
[ -f $file ] && echo "Exists" # ? 錯誤:too many arguments# 雙括號正確處理
[[ -f $file ]] && echo "Exists" # ? 正確
2. 支持高級模式匹配
[[ ]]
支持通配符擴展和正則表達式:
# 通配符匹配(* 匹配任意字符)
[[ "hello.jpg" == *.jpg ]] && echo "JPEG file" # ? 輸出# 正則表達式匹配(=~ 操作符)
[[ "hello123" =~ ^[a-z]+[0-9]+$ ]] && echo "Valid ID" # ? 輸出
3. 更直觀的邏輯運算符
可直接使用 &&
/||
代替 -a
/-o
:
# 單括號(必須用 -a/-o)
[ -f file.txt -a -r file.txt ] && echo "Readable file"# 雙括號(可直接用 &&/||)
[[ -f file.txt && -r file.txt ]] && echo "Readable file" # ? 更直觀
4. 支持字符串比較運算符
字符串比較時不需要轉義:
# 單括號需轉義 >(否則被識別為重定向)
[ "apple" \> "banana" ] && echo "True"# 雙括號無需轉義
[[ "apple" > "banana" ]] && echo "True" # ? 更簡潔
5. 防止路徑名擴展
[[ ]]
不會展開通配符(如 *
):
# 當前目錄有 a.txt, b.txt
[ "*.txt" == *.txt ] && echo "Equal" # ? 實際比較 "*.txt" == "a.txt b.txt"
[[ "*.txt" == *.txt ]] && echo "Equal" # ? 正確比較字符串(輸出 Equal)
6. 增強的數值比較
支持更自然的數值比較語法:
num=10
[[ num -gt 5 ]] && echo "大于 5" # ? 傳統寫法
(( num > 5 )) && echo "大于 5" # ? 推薦數值比較寫法(雙括號專用于算術)
何時使用?
場景 | 建議語法 |
---|---|
需要兼容 /bin/sh | [ ] (POSIX) |
Bash 腳本(推薦) | [[ ]] |
數值比較 | (( )) |
經典示例對比
# 檢查文件是否存在且可讀(兼容 POSIX)
[ -f "my file.txt" -a -r "my file.txt" ] && echo "OK"# Bash 推薦寫法(更安全簡潔)
[[ -f my\ file.txt && -r my\ file.txt ]] && echo "OK"
💡 總結:在 Bash 腳本中優先使用
[[ ]]
,它能避免許多常見陷阱,提供更強大的模式匹配能力,同時代碼更簡潔直觀。但若需兼容 POSIX Shell(如dash
),則需使用[ ]
。