Linux?Shell腳本之流程控制語句舉例詳解
在掌握了Shell腳本的變量與運算之后,流程控制是構(gòu)建復(fù)雜和實用腳本的關(guān)鍵。它允許腳本根據(jù)不同的條件來選擇執(zhí)行路徑,或重復(fù)執(zhí)行特定任務(wù),從而實現(xiàn)腳本的靈活性與自動化。
思維導(dǎo)圖



一、條件判斷
if 語句是最基本的條件控制結(jié)構(gòu),它評估一個命令的退出狀態(tài)碼 (exit code)。如果退出碼為 0 (成功),則條件為真;如果為非 0 (失敗),則條件為假。
if 的基本結(jié)構(gòu)
格式:
if [ 條件判斷 ]; then # 條件為真時執(zhí)行的代碼塊 fi
代碼示例:檢查文件是否存在
#!/bin/bash TARGET_FILE="/etc/hosts" if [ -f "$TARGET_FILE" ]; then echo "文件 '$TARGET_FILE' 存在。" fi
if...else 結(jié)構(gòu)
格式:
if [ 條件判斷 ]; then # 條件為真時執(zhí)行的代碼塊 else # 條件為假時執(zhí)行的代碼塊 fi
代碼示例:判斷目錄是否存在
#!/bin/bash TARGET_DIR="/var/log/non_existent_dir" if [ -d "$TARGET_DIR" ]; then echo "目錄 '$TARGET_DIR' 存在。" else echo "目錄 '$TARGET_DIR' 不存在,將嘗試創(chuàng)建。" mkdir -p "$TARGET_DIR" fi
if...elif...else 結(jié)構(gòu)
格式:
if [ 條件1 ]; then # 條件1為真時執(zhí)行 elif [ 條件2 ]; then # 條件1為假,但條件2為真時執(zhí)行 else # 以上所有條件都為假時執(zhí)行 fi
代碼示例:根據(jù)HTTP狀態(tài)碼判斷響應(yīng)
#!/bin/bash HTTP_CODE=200 if [ $HTTP_CODE -eq 200 ]; then echo "請求成功 (OK)" elif [ $HTTP_CODE -eq 404 ]; then echo "資源未找到 (Not Found)" elif [ $HTTP_CODE -eq 500 ]; then echo "服務(wù)器內(nèi)部錯誤 (Internal Server Error)" else echo "收到未知的HTTP狀態(tài)碼: $HTTP_CODE" fi
條件判斷的實現(xiàn):test 和 [ ]
在Shell中,if 后的條件通常由 test 命令或其等價形式 [ ... ] 來實現(xiàn)。[[ ... ]] 是 [ ... ] 的擴展版本,提供了更多功能 (如模式匹配、邏輯與/或)。
常見判斷類型:
文件測試:
-f(是普通文件?),-d(是目錄?),-e(存在?),-s(大小非0?),-r(可讀?),-w(可寫?),-x(可執(zhí)行?) 字符串比較:"$str1" = "$str2","$str1" != "$str2",-z "$str"(字符串為空?),-n "$str"(字符串非空?) 整數(shù)比較:-eq(等于),-ne(不等于),-gt(大于),-ge(大于等于),-lt(小于),-le(小于等于)
二、循環(huán)結(jié)構(gòu)
循環(huán)用于重復(fù)執(zhí)行一段代碼,直到滿足某個退出條件。
for 循環(huán)
for 循環(huán)擅長遍歷一個列表 (字符串、文件名、數(shù)字序列等) 或進行C語言風(fēng)格的數(shù)值循環(huán)。
格式 (遍歷列表):
for variable_name in item1 item2 item3 ...; do # 循環(huán)體 done
代碼示例 (遍歷并重命名文件):
#!/bin/bash
# 將所有 .txt 文件重命名為 .txt.bak
for filename in *.txt; do
if [ -f "$filename" ]; then
echo "正在備份: $filename -> ${filename}.bak"
mv "$filename" "${filename}.bak"
fi
done
格式 (C風(fēng)格數(shù)值循環(huán)):
for (( initialization; condition; step )); do # 循環(huán)體 done
代碼示例 (執(zhí)行三次ping測試):
#!/bin/bash TARGET_HOST="8.8.8.8" for (( i=1; i<=3; i++ )); do echo "--- 第 $i 次 PING 測試 ---" ping -c 1 "$TARGET_HOST" done
while 循環(huán)
while 循環(huán)在每次迭代前檢查條件,只要條件為真,就繼續(xù)執(zhí)行循環(huán)體。
格式:
while [ 條件判斷 ]; do # 循環(huán)體 done
代碼示例:逐行讀取文件
#!/bin/bash
CONFIG_FILE="/etc/fstab"
while read -r line; do
# 忽略注釋和空行
if [[ "$line" =~ ^# || -z "$line" ]]; then
continue
fi
echo "讀取到配置行: $line"
done < "$CONFIG_FILE"
until 循環(huán)
until 循環(huán)與 while 邏輯相反:只要條件為假,就繼續(xù)執(zhí)行循環(huán)體,直到條件變?yōu)檎娌磐V埂?/p>
格式:
until [ 條件判斷 ]; do # 循環(huán)體 done
代碼示例:等待服務(wù)端口啟動
#!/bin/bash
PORT=8080
TIMEOUT=10
COUNT=0
until nc -z localhost $PORT >/dev/null 2>&1; do
if [ $COUNT -ge $TIMEOUT ]; then
echo "等待端口 $PORT 超時!"
exit 1
fi
echo "端口 $PORT 尚未啟動,等待1秒..."
sleep 1
COUNT=$((COUNT + 1))
done
echo "端口 $PORT 已成功啟動!"
循環(huán)控制:break 和 continue
break: 立即從當前循環(huán)中完全跳出。continue: 跳過當前循環(huán)的剩余部分,直接開始下一次迭代。
代碼示例:在循環(huán)中處理文件
#!/bin/bash
for file in /var/log/*; do
if [ -d "$file" ]; then
continue # 如果是目錄,則跳過
fi
echo "正在處理文件: $file"
if [ -s "$file" ] && grep -q "ERROR" "$file"; then
echo "在文件 '$file' 中找到錯誤,停止處理。"
break # 找到錯誤后,完全停止
fi
done
三、分支選擇
case 語句提供了一種更清晰的方式來處理多重條件分支,是 if...elif...else 的一種替代方案,特別適合基于單個變量的值進行匹配。
格式:
case $variable in
pattern1)
# 匹配 pattern1 時執(zhí)行
;;
pattern2|pattern3)
# 匹配 pattern2 或 pattern3 時執(zhí)行
;;
*)
# 默認情況,當以上模式都不匹配時執(zhí)行
;;
esac
代碼示例:腳本參數(shù)解析
#!/bin/bash
ACTION=$1
case $ACTION in
start)
echo "正在啟動服務(wù)..."
# systemctl start my_service
;;
stop)
echo "正在停止服務(wù)..."
# systemctl stop my_service
;;
status)
echo "檢查服務(wù)狀態(tài)..."
# systemctl status my_service
;;
*)
echo "用法: $0 {start|stop|status}"
exit 1
;;
esac
練習(xí)題
題目:
- 文件權(quán)限檢查:寫一個腳本,接收一個文件名作為參數(shù) (
$1)。腳本需要判斷當前用戶對該文件是否同時擁有讀、寫、執(zhí)行權(quán)限。如果同時擁有,打印 "Full permissions granted";否則打印 "Permissions incomplete"。 - 字符串與邏輯判斷:寫一個腳本,檢查變量
ENVIRONMENT的值。如果值是production并且 變量FORCE_DEPLOY的值不是true,則打印 "Safety check passed: Not a forced production deploy." 并退出;否則,打印 "Proceeding with deployment."。 - C風(fēng)格
for循環(huán)與算術(shù):使用C風(fēng)格的for循環(huán),打印出從10到20之間所有的偶數(shù) (包括10和20)。 for循環(huán)與通配符:寫一個腳本,查找/var/log目錄下所有以.log結(jié)尾的非空文件,并打印出它們的文件名。while循環(huán)讀取標準輸入:寫一個腳本,持續(xù)讀取用戶從鍵盤輸入的內(nèi)容,直到用戶輸入quit為止。對于非quit的輸入,腳本應(yīng)該將其回顯到屏幕上。until循環(huán)與命令退出碼:grep命令在找到匹配項時退出碼為0,找不到時為1。寫一個until循環(huán),每隔2秒檢查一次系統(tǒng)日志 (/var/log/messages或journalctl -f的輸出,為簡化可檢查一個普通文件) 是否出現(xiàn)了 "critical error" 字符串,一旦出現(xiàn)就打印 "Critical error detected!" 并退出。- 嵌套循環(huán)與
break n:寫一個嵌套循環(huán)。外層循環(huán)從1到3,內(nèi)層循環(huán)從1到3。在內(nèi)層循環(huán)中,如果內(nèi)外兩個循環(huán)變量 (i和j) 相等,則同時跳出內(nèi)外兩層循環(huán)。每次循環(huán)都打印當前的i和j的值。 case語句與通配符:寫一個case語句,判斷一個文件名變量FILENAME的文件類型。如果文件名以.log結(jié)尾,打印 "Log file";如果以.tar.gz或.tgz結(jié)尾,打印 "Compressed archive";如果以.sh結(jié)尾,打印 "Shell script";其他情況打印 "Unknown file type"。select菜單 (高級):select是一個特殊的循環(huán)結(jié)構(gòu),用于創(chuàng)建交互式菜單。寫一個腳本,使用select讓用戶從 "Start", "Stop", "Restart", "Exit" 四個選項中選擇一個操作,并根據(jù)用戶的選擇打印相應(yīng)的信息。當用戶選擇 "Exit" 時,腳本退出。
答案與解析:
- 文件權(quán)限檢查:
#!/bin/bash if [ -z "$1" ]; then echo "用法: $0 <文件名>" exit 1 fi if [ -r "$1" ] && [ -w "$1" ] && [ -x "$1" ]; then echo "Full permissions granted" else echo "Permissions incomplete" fi
- 解析:
if語句中的-r,-w,-x是文件測試操作符,分別檢查讀、寫、執(zhí)行權(quán)限。&&是邏輯與操作符,要求所有條件都為真才執(zhí)行then塊。
- 字符串與邏輯判斷:
#!/bin/bash ENVIRONMENT="production" FORCE_DEPLOY="false" if [[ "$ENVIRONMENT" == "production" && "$FORCE_DEPLOY" != "true" ]]; then echo "Safety check passed: Not a forced production deploy." exit 0 else echo "Proceeding with deployment." fi
- 解析: 使用了
[[ ... ]]擴展測試,它內(nèi)部支持&&(邏輯與) 和!=(字符串不等于) 操作符,語法更自然。
- C風(fēng)格
for循環(huán)與算術(shù):
#!/bin/bash for (( num=10; num<=20; num+=2 )); do echo $num done
- 解析: C風(fēng)格的
for循環(huán)通過初始化num=10,條件num<=20,以及步進num+=2來精確控制循環(huán),直接打印出范圍內(nèi)的偶數(shù)。
for循環(huán)與通配符:
#!/bin/bash
for logfile in /var/log/*.log; do
if [ -s "$logfile" ]; then
echo "找到非空日志文件: $(basename "$logfile")"
fi
done
- 解析:
*.log是一個通配符,for循環(huán)會遍歷所有匹配的文件名。-s文件測試操作符用于判斷文件大小是否大于零。basename命令用于提取文件名,去除路徑。
while循環(huán)讀取標準輸入:
#!/bin/bash
echo "請輸入內(nèi)容 (輸入 'quit' 退出):"
while read -r input_line; do
if [ "$input_line" == "quit" ]; then
break
fi
echo "你輸入了: $input_line"
done
- 解析:
while read -r input_line是讀取標準輸入的標準模式。循環(huán)會一直持續(xù),直到read命令失敗 (例如,用戶按下Ctrl+D) 或遇到break。
until循環(huán)與命令退出碼:
#!/bin/bash LOG_FILE_TO_CHECK="my_app.log" touch $LOG_FILE_TO_CHECK # 創(chuàng)建一個空文件用于測試 echo "正在監(jiān)控 '$LOG_FILE_TO_CHECK' ..." # 在另一個終端執(zhí)行 echo "critical error" >> my_app.log 來觸發(fā) until grep -q "critical error" "$LOG_FILE_TO_CHECK"; do sleep 2 done echo "Critical error detected!"
- 解析:
until循環(huán)的條件是命令本身 (grep -q ...)。只要grep找不到字符串 (退出碼非0,條件為假),循環(huán)就繼續(xù)。一旦找到 (退出碼為0,條件為真),循環(huán)終止。
- 嵌套循環(huán)與
break n:
#!/bin/bash
for (( i=1; i<=3; i++ )); do
echo "外層循環(huán): i=$i"
for (( j=1; j<=3; j++ )); do
echo " 內(nèi)層循環(huán): j=$j"
if [ $i -eq $j ]; then
echo " i 等于 j,跳出所有循環(huán)!"
break 2 # '2' 表示跳出兩層循環(huán)
fi
done
done
- 解析:
break n命令可以跳出指定層數(shù)的循環(huán)。break 1(或break) 只跳出當前層,break 2跳出當前層和其外一層。
case語句與通配符:
#!/bin/bash
FILENAME="archive-2023.tar.gz"
case $FILENAME in
*.log)
echo "Log file"
;;
*.tar.gz|*.tgz)
echo "Compressed archive"
;;
*.sh)
echo "Shell script"
;;
*)
echo "Unknown file type"
;;
esac
- 解析:
case語句的模式支持通配符,如*(匹配任意字符序列)。|用于分隔多個模式,表示“或”。
select菜單:
#!/bin/bash
PS3="請選擇一個操作 (輸入數(shù)字): "
options=("Start" "Stop" "Restart" "Exit")
select opt in "${options[@]}"; do
case $opt in
"Start")
echo "正在啟動..."
;;
"Stop")
echo "正在停止..."
;;
"Restart")
echo "正在重啟..."
;;
"Exit")
echo "退出腳本。"
break
;;
*)
echo "無效選項 '$REPLY',請重新選擇。"
;;
esac
done
- 解析:
select會自動生成一個帶編號的菜單。用戶的輸入編號會被翻譯成對應(yīng)的選項值 (賦給變量opt),而原始輸入則保存在$REPLY中。
總結(jié)
到此這篇關(guān)于Linux Shell腳本之流程控制語句舉例詳解的文章就介紹到這了,更多相關(guān)Linux Shell流程控制語句內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Shell腳本實現(xiàn)監(jiān)控rsync數(shù)據(jù)是否傳輸完
這篇文章主要介紹了Shell腳本實現(xiàn)監(jiān)控rsync數(shù)據(jù)是否傳輸完,本文直接給出實現(xiàn)代碼,需要的朋友可以參考下2014-12-12
shell腳本ssh遠程執(zhí)行命令給變量賦值的問題解決
本文主要介紹了shell腳本ssh遠程執(zhí)行命令給變量賦值的問題解決,就是從A機器通過SSH方式到B機器,并執(zhí)行相關(guān)的命令,具有一定的參考價值,感興趣的可以了解一下2023-07-07
shell腳本學(xué)習(xí)指南[三](Arnold?Robbins?&?Nelson?H.F.?Beebe著)
這篇文章主要介紹了shell腳本學(xué)習(xí)指南[三](Arnold?Robbins?&?Nelson?H.F.?Beebe著),需要的朋友可以參考下2014-02-02
Shell腳本實現(xiàn)自動備份網(wǎng)站和數(shù)據(jù)庫并上傳到云存儲
這篇文章主要為大家詳細介紹了Shell腳本實現(xiàn)自動備份網(wǎng)站和數(shù)據(jù)庫并上傳到云存儲的相關(guān)知識,文中的示例代碼講解詳細,希望對大家有所幫助2025-11-11
獲取站點的各類響應(yīng)時間(dns解析時間,響應(yīng)時間,傳輸時間)
有時候為了測試網(wǎng)絡(luò)情況,需要返回每個階段的耗時時間,比如DNS解析耗時,建立連接所消耗的時間,從建立連接到準備傳輸所使用的時間,從建立連接到傳輸開始所使用的時間,整個過程耗時,下載的數(shù)據(jù)量,下載速度,上傳數(shù)據(jù)量,上傳速度等等2014-03-03

