if條件語句的語法及案例
一、基本語法結構
1. 單條件判斷
if [ 條件 ]; then命令1命令2...
fi
2. 雙分支(if-else)
if [ 條件 ]; then條件為真時執行的命令
else條件為假時執行的命令
fi
3. 多分支(if-elif-else)
if [ 條件1 ]; then命令1
elif [ 條件2 ]; then命令2
else命令3
fi
4. 嵌套結構
if [ 條件1 ]; thenif [ 條件2 ]; then命令1fi
else命令2
fi
5.多條件判斷語句case
case 變量名 in
值1)
指令1
;;
值2)
指令2
;;
值3)
指令3
;;
*)
默認
esac
二、條件測試語法
1. 數值比較
if [ $a -eq 10 ]; then ... # 等于
if [ $a -ne 10 ]; then ... # 不等于
if [ $a -gt 10 ]; then ... # 大于
if [ $a -lt 10 ]; then ... # 小于
if [ $a -ge 10 ]; then ... # 大于等于
if [ $a -le 10 ]; then ... # 小于等于
2. 字符串比較
if [ "$str" = "hello" ]; then ... # 等于(注意用雙引號)
if [ "$str" != "hello" ]; then ... # 不等于
if [ -z "$str" ]; then ... # 字符串為空
if [ -n "$str" ]; then ... # 字符串非空
3. 文件測試
if [ -e "file.txt" ]; then ... # 文件或目錄存在
if [ -f "file.txt" ]; then ... # 文件存在且為普通文件
if [ -d "dir" ]; then ... # 目錄存在
if [ -r "file.txt" ]; then ... # 文件可讀
if [ -w "file.txt" ]; then ... # 文件可寫
if [ -x "script.sh" ]; then ... # 文件可執行
4. 邏輯組合
# 使用 &&(邏輯與)
if [ -f "file.txt" ] && [ -r "file.txt" ]; then ...# 使用 ||(邏輯或)
if [ $a -eq 1 ] || [ $a -eq 2 ]; then ...# 使用 !(邏輯非)
if [ ! -d "dir" ]; then ...
三、案例示例
1. 判斷文件是否存在
#!/bin/bashif [ -e "data.txt" ]; thenecho "文件存在"cat data.txt
elseecho "文件不存在,創建中..."touch data.txt
fi
2. 檢查參數數量
#!/bin/bashif [ $# -ne 2 ]; thenecho "錯誤:需要兩個參數" >&2echo "用法:$0 參數1 參數2" >&2exit 1
elseecho "參數1: $1"echo "參數2: $2"
fi
3. 數值比較
#!/bin/bashread -p "請輸入一個數字: " numif [ "$num" -lt 0 ]; thenecho "負數"
elif [ "$num" -eq 0 ]; thenecho "零"
elseecho "正數"
fi
4. 字符串匹配
#!/bin/bashread -p "請輸入yes或no: " answerif [ "$answer" = "yes" ]; thenecho "你選擇了yes"
elif [ "$answer" = "no" ]; thenecho "你選擇了no"
elseecho "無效輸入"
fi
5. 檢查命令執行結果
#!/bin/bashif grep -q "error" log.txt; thenecho "日志中發現錯誤"mail -s "系統異常" admin@example.com < log.txt
elseecho "系統正常"
fi
6. 嵌套條件
#!/bin/bashread -p "請輸入年齡: " ageif [ "$age" -ge 18 ]; thenif [ "$age" -lt 60 ]; thenecho "成年人"elseecho "老年人"fi
elseecho "未成年人"
fi
7.case語句使用?
由用戶從鍵盤輸入一個字符,并判斷該字符是否為字母、數字或者其他字符, 并輸出
相應的提示信息。[root@kittod ~]# cat in.sh
#!/bin/bash
read -p "Please enter a character, press enter to continue: " KEY
case "$KEY" in
[a-z]|[A-Z])
echo "Input is letter"
;;
[0-9])
echo "Input is number"
;;
*)
echo "Input is other characters"
esac
四、高級語法
1. 使用?[[ ]]
?替代?[ ]
# [[ ]] 支持更復雜的表達式
if [[ "$str" == hello* ]]; then ... # 模式匹配
if [[ $a -gt 10 && $b -lt 20 ]]; then ... # 邏輯組合
2. 使用?(( ))
?進行數值比較
if (( a > 10 )); then ... # 無需引號,支持算術表達式
3. 使用?test
?命令
if test -f "file.txt"; then ... # 等同于 [ -f "file.txt" ]
五、常見錯誤及注意事項
-
空格問題:
[
?和?]
?內部必須有空格,例如:# 正確 if [ "$a" -eq 10 ]; then ...# 錯誤(缺少空格) if ["$a"-eq 10]; then ...
-
變量引用加引號:
防止變量為空時導致語法錯誤:# 正確 if [ -z "$str" ]; then ...# 錯誤(當 $str 為空時會變成 [ -z ],語法錯誤) if [ -z $str ]; then ...
-
整數比較用?
-eq
,而非?=
:# 正確(數值比較) if [ "$a" -eq 10 ]; then ...# 錯誤(字符串比較) if [ "$a" = 10 ]; then ...
六、總結
語法結構 | 適用場景 | 示例 |
---|---|---|
[ 條件 ] | 傳統條件測試 | [ -f "file.txt" ] |
[[ 條件 ]] | 增強型條件測試(推薦) | [[ $a -gt 10 && $b -lt 20 ]] |
(( 條件 )) | 純數值比較 | (( a > 10 )) |
test 條件 | 等同于?[ ] | test -d "dir" |
合理使用?if
?條件語句可以讓腳本根據不同情況執行不同邏輯,增強腳本的靈活性和健壯性。
exit詳細介紹
一、基本語法
exit [N]
N
:可選參數,表示退出狀態碼(整數,范圍通常為?0~255
)。- 若省略?
N
,exit
?將返回最后一條命令的執行狀態碼。 - 狀態碼可通過?
$?
?變量在腳本外獲取(例如在終端中執行?echo $?
)。
- 若省略?
二、退出狀態碼的含義
1. 標準狀態碼
0
:表示腳本正常執行完畢(無錯誤)。- 非?
0
:表示腳本異常終止或執行過程中出現錯誤(常見值:1~255
)。
2. 常用非零狀態碼(約定俗成)
狀態碼 | 含義說明 |
---|---|
1 | 通用錯誤(例如參數錯誤、文件不存在)。 |
2 | Shell 內置命令錯誤(如?cd ?命令失敗)。 |
126 | 命令存在但不可執行(如腳本無執行權限)。 |
127 | 命令不存在(如拼寫錯誤的命令)。 |
130 | 腳本被中斷信號(如?Ctrl+C )終止。 |
255 | 非法退出狀態碼(超出范圍的數值會被取模為?255 ,例如?exit 300 ?等價于?exit 44 )。 |
三、exit
?的典型用法場景
1. 正常退出腳本(返回?0
)
#!/bin/bash
echo "腳本執行完成"
exit # 等價于 exit 0
? - 執行后,通過?
echo $?
?可獲取狀態碼?0
。
2. 異常退出并返回錯誤碼
#!/bin/bash
# 檢查文件是否存在
if [ ! -f "data.txt" ]; thenecho "錯誤:文件 data.txt 不存在!"exit 1 # 退出并返回錯誤碼 1
fiecho "文件存在,繼續執行..."
exit 0 # 正常退出
? - 若文件不存在,腳本輸出錯誤信息后終止,返回?
1
;否則返回?0
。
3. 根據命令執行結果決定是否退出
#!/bin/bash
# 嘗試創建目錄
mkdir -p "/data/app"
if [ $? -ne 0 ]; then # $? 存儲上一條命令的狀態碼echo "創建目錄失敗!"exit 2 # 返回錯誤碼 2
fiecho "目錄創建成功"
exit 0
? - 通過?
$?
?判斷前一條命令(mkdir
)是否執行成功,失敗則退出并返回?2
。
4. 在函數中退出腳本
#!/bin/bash
check_disk_space() {free_space=$(df -h / | awk 'NR==2 {print $4}')if [ "$free_space" -lt "10G" ]; thenecho "磁盤空間不足!"exit 100 # 在函數中直接退出腳本,返回 100fi
}check_disk_space
echo "磁盤空間充足" # 若空間不足,此行不會執行
exit 0
? - 函數中調用?
exit
?會直接終止腳本,無需返回值傳遞。
四、注意事項
1. 狀態碼的范圍限制
- 狀態碼必須是?0~255 之間的整數,超出范圍會被自動取模(例如?
exit 300
?等價于?exit 44
,因為?300 mod 256 = 44
)。
2. 子進程中的?exit
- 在子 Shell(如?
(...)
?或管道)中執行?exit
,僅會終止子 Shell,不影響父腳本。例如:(echo "子 Shell 開始"exit 1 # 子 Shell 退出,返回碼 1 ) echo "父腳本繼續執行" # 此行會執行 echo $? # 輸出 1(子 Shell 的退出碼)
3. 與?return
?的區別
exit
:用于終止整個腳本,并返回狀態碼給系統(適用于腳本主流程)。return
:用于終止當前函數,并返回狀態碼給調用者(僅在函數內部使用)。func() {return 5 # 函數返回 5,不終止腳本 } func echo $? # 輸出 5(函數的返回值)
五、最佳實踐
- 明確返回狀態碼:
- 正常執行時返回?
0
,錯誤時返回有意義的非零碼(如?1
、2
?等),便于外部腳本或監控工具判斷執行結果。
- 正常執行時返回?
- 提前退出:
- 在腳本開頭檢查必要條件(如權限、文件存在性),不滿足時盡早退出并提示錯誤。
- 避免濫用:
- 僅在需要終止腳本時使用?
exit
,避免在循環或分支中無意義地退出。
- 僅在需要終止腳本時使用?
六、案例:帶狀態碼的腳本
#!/bin/bash
# 檢查當前用戶是否為 root
if [ "$USER" != "root" ]; thenecho "錯誤:必須以 root 身份運行!" >&2 # 錯誤信息輸出到 stderrexit 1 # 非 root 用戶,返回 1
fi# 檢查磁盤空間
free_space=$(df -BM / | awk 'NR==2 {print $4}' | tr -d 'M')
if [ "$free_space" -lt 100 ]; thenecho "警告:磁盤剩余空間不足 100MB!"exit 2 # 空間不足,返回 2
fiecho "腳本執行成功"
exit 0 # 正常退出,返回 0
? - 執行結果:
$ ./script.sh # 非 root 用戶執行 錯誤:必須以 root 身份運行! $ echo $? # 查看狀態碼 1$ sudo ./script.sh # root 用戶執行且空間充足 腳本執行成功 $ echo $? 0
通過合理使用?exit
,可以讓腳本更健壯、更易調試,尤其在自動化運維和腳本鏈調用中至關重要。
循環控制
一、for
?循環
1. 基本語法(遍歷列表)
for 變量名 in 列表元素
do命令序列
done
- 列表元素:可以是空格分隔的字符串、文件列表、命令輸出等。
- 執行邏輯:變量依次取列表中的每個值,執行循環體。
2. 示例
示例 1:遍歷字符串列表
for fruit in apple banana cherry
doecho "當前水果:$fruit"
done
? 輸出:
?當前水果:apple
當前水果:banana
當前水果:cherry
示例 2:遍歷文件列表
for file in /etc/*.conf
doif [ -f "$file" ]; thenecho "文件:$file"fi
done
示例 3:遍歷命令輸出
for line in $(cat users.txt)
doecho "用戶:$line"
done
3. C 語言風格?for
?循環(適用于數值迭代)
for ((初始值; 條件; 增量))
do命令序列
done
? - 初始值:變量初始化(如?
i=1
)。 - 條件:循環繼續的條件(如?
i<=10
)。 - 增量:變量更新(如?
i++
)。
示例:
?for ((i=1; i<=5; i++))
doecho "迭代次數:$i"
done
? 輸出:
?迭代次數:1
迭代次數:2
迭代次數:3
迭代次數:4
迭代次數:5
二、while
?循環
1. 基本語法(條件為真時循環)
while [ 條件 ]
do命令序列
done
? - 執行邏輯:先判斷條件,若為真則執行循環體,重復直至條件為假。
2. 示例
示例 1:數值累加
sum=0
i=1
while [ $i -le 10 ]
dosum=$((sum + i))i=$((i + 1))
done
echo "1+2+...+10 = $sum"
? 輸出:
?1+2+...+10 = 55
示例 2:讀取文件逐行處理
while read -r line
doecho "行內容:$line"
done < file.txt
3. 無限循環
while true
doecho "無限循環中...(按 Ctrl+C 終止)"sleep 1
done
三、until
?循環
1. 基本語法(條件為假時循環)
until [ 條件 ]
do命令序列
done
? - 執行邏輯:先判斷條件,若為假則執行循環體,重復直至條件為真(與?
while
?相反)。
2. 示例
n=10
until [ $n -le 0 ]
doecho "$n"n=$((n - 1))
done
? 輸出:
?10
9
8
7
6
5
4
3
2
1
四、循環控制關鍵字
1.?break
:跳出當前循環
- 用法:
for i in 1 2 3 4 5 doif [ $i -eq 3 ]; thenbreak # 當 i=3 時,跳出循環fiecho $i done
輸出:
?1
2
2.?continue
:跳過當前迭代,繼續下一次循環
- 用法:
for i in 1 2 3 4 5 doif [ $i -eq 3 ]; thencontinue # 當 i=3 時,跳過本次循環fiecho $i done
輸出:
?1
2
4
5
3.?break n
?和?continue n
:控制多層循環
n
?表示跳出 / 跳過的循環層數(默認?n=1
,即當前層)。- 示例(雙層循環):
for i in a b c dofor j in 1 2 3doif [ $j -eq 2 ]; thenbreak 2 # 跳出兩層循環(即整個循環)fiecho "$i-$j"done done
輸出:
?a-1
五、循環常見應用場景
1. 批量文件操作
# 刪除所有 .bak 文件
for file in *.bak
dorm -f "$file"echo "已刪除:$file"
done
2. 進度條模擬
echo -n "進度:["
for ((i=0; i<=10; i++))
dosleep 0.5echo -n "#"
done
echo "] 完成"
? 輸出:
?進度:##########] 完成
3. 交互式循環(用戶輸入控制)
while true
doread -p "是否繼續?(y/n): " choicecase $choice in[Yy])echo "繼續執行...";;[Nn])echo "退出程序"break;;*)echo "無效輸入,請重新輸入";;esac
done
六、注意事項
-
變量引用加引號:
避免列表元素包含空格時被錯誤分割:# 錯誤(元素包含空格時分割錯誤) for str in "hello world" "hi bash" doecho $str # 正確輸出每個元素 done
-
避免無限循環:
在?while
/until
?循環中確保條件最終為真 / 假,否則需用?Ctrl+C
?強制終止。 -
多層循環性能:
嵌套循環可能影響性能,盡量優化循環邏輯或使用更高效的工具(如?awk
、sed
)。
七、循環與數組結合
1. 遍歷數組元素
arr=("apple" "banana" "cherry")
for fruit in "${arr[@]}"
doecho "數組元素:$fruit"
done
2. 遍歷數組索引
arr=("a" "b" "c")
for i in "${!arr[@]}" # ${!arr[@]} 獲取數組索引
doecho "索引 $i:${arr[$i]}"
done
? 輸出:
?索引 0:a
索引 1:b
索引 2:c
總結
循環類型 | 特點 | 適用場景 |
---|---|---|
for ?循環 | 遍歷固定列表或數值范圍,簡潔直觀 | 批量處理文件、已知次數的任務 |
while ?循環 | 條件為真時持續執行,適合未知次數的循環 | 讀取文件、交互式操作 |
until ?循環 | 條件為假時持續執行,邏輯與?while ?相反 | 逆序計數、條件反轉場景 |
break /continue | 控制循環流程,跳出或跳過迭代 | 復雜邏輯分支、提前終止循環 |