條件判斷與迴圈

部分內容由 LLM 生成,尚未經過人工驗證。

Shell 條件判斷、迴圈與流程控制。

if/elif/else 條件語句

#!/bin/bash

age=20

if [ $age -lt 18 ]; then
    echo "Minor"
elif [ $age -lt 65 ]; then
    echo "Adult"
else
    echo "Senior"
fi

單行寫法

if [ $age -ge 18 ]; then echo "Adult"; fi

測試表達式

Shell 提供兩種測試語法:[ ][[ ]]

[ ] vs [[ ]]

特性[ ][[ ]]
POSIX 相容✗ (Bash/Zsh)
邏輯運算-a, -o&&, ||
模式匹配
正則表達式
變數引號必須可選
# [ ] 需要引號保護變數
if [ "$var" = "value" ]; then
    echo "Match"
fi

# [[ ]] 更安全(建議使用)
if [[ $var == "value" ]]; then
    echo "Match"
fi

# [[ ]] 支援模式匹配
if [[ $filename == *.txt ]]; then
    echo "Text file"
fi

# [[ ]] 支援正則表達式
if [[ $email =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
    echo "Valid email"
fi

檔案測試

file="test.txt"

# 檔案存在
if [[ -e $file ]]; then echo "Exists"; fi

# 是否為檔案
if [[ -f $file ]]; then echo "File"; fi

# 是否為目錄
if [[ -d $file ]]; then echo "Directory"; fi

# 是否可讀/寫/執行
if [[ -r $file ]]; then echo "Readable"; fi
if [[ -w $file ]]; then echo "Writable"; fi
if [[ -x $file ]]; then echo "Executable"; fi

# 檔案非空
if [[ -s $file ]]; then echo "Not empty"; fi

數值比較

a=10
b=20

if [[ $a -eq $b ]]; then echo "Equal"; fi         # 等於
if [[ $a -ne $b ]]; then echo "Not equal"; fi     # 不等於
if [[ $a -lt $b ]]; then echo "Less than"; fi     # 小於
if [[ $a -le $b ]]; then echo "Less or equal"; fi # 小於等於
if [[ $a -gt $b ]]; then echo "Greater"; fi       # 大於
if [[ $a -ge $b ]]; then echo "Greater or equal"; fi # 大於等於

字串比較

str1="hello"
str2="world"

if [[ $str1 == $str2 ]]; then echo "Equal"; fi
if [[ $str1 != $str2 ]]; then echo "Not equal"; fi

# 字串為空
if [[ -z $str1 ]]; then echo "Empty"; fi

# 字串非空
if [[ -n $str1 ]]; then echo "Not empty"; fi

邏輯運算

age=25
name="Alice"

# AND
if [[ $age -ge 18 && $name == "Alice" ]]; then
    echo "Adult Alice"
fi

# OR
if [[ $age -lt 18 || $age -gt 65 ]]; then
    echo "Not working age"
fi

# NOT
if [[ ! -f "file.txt" ]]; then
    echo "File not found"
fi

case 語句

#!/bin/bash

fruit="apple"

case $fruit in
    apple)
        echo "Red fruit"
        ;;
    banana)
        echo "Yellow fruit"
        ;;
    grape|cherry)
        echo "Small fruit"
        ;;
    *)
        echo "Unknown fruit"
        ;;
esac

模式匹配

case $filename in
    *.txt)
        echo "Text file"
        ;;
    *.jpg|*.png)
        echo "Image file"
        ;;
    [Mm]akefile)
        echo "Makefile"
        ;;
    *)
        echo "Other file"
        ;;
esac

for 迴圈

Range-based for

# 迭代列表
for item in apple banana cherry; do
    echo "$item"
done

# 迭代檔案
for file in *.txt; do
    echo "Processing $file"
done

# 迭代命令輸出
for user in $(cat /etc/passwd | cut -d: -f1); do
    echo "User: $user"
done

# 迭代陣列
fruits=("apple" "banana" "cherry")
for fruit in "${fruits[@]}"; do
    echo "$fruit"
done

C-style for

# 數值範圍
for ((i=0; i<10; i++)); do
    echo "Number: $i"
done

# 倒數
for ((i=10; i>0; i--)); do
    echo "Countdown: $i"
done

Brace Expansion

# 序列擴展
for i in {1..10}; do
    echo "$i"
done

# 指定步進
for i in {0..100..10}; do
    echo "$i"
done

# 字母序列
for char in {a..z}; do
    echo "$char"
done

while 迴圈

# 基本 while
count=0
while [ $count -lt 5 ]; do
    echo "Count: $count"
    ((count++))
done

# 讀取檔案
while IFS= read -r line; do
    echo "Line: $line"
done < file.txt

# 無限迴圈
while true; do
    echo "Running..."
    sleep 1
done

until 迴圈

# until 直到條件為真才停止
count=0
until [ $count -ge 5 ]; do
    echo "Count: $count"
    ((count++))
done

break 與 continue

# break - 跳出迴圈
for i in {1..10}; do
    if [ $i -eq 5 ]; then
        break
    fi
    echo "$i"
done

# continue - 跳過本次迭代
for i in {1..10}; do
    if [ $i -eq 5 ]; then
        continue
    fi
    echo "$i"
done

# 巢狀迴圈 break
for i in {1..3}; do
    for j in {1..3}; do
        if [ $j -eq 2 ]; then
            break 2  # 跳出兩層迴圈
        fi
        echo "$i-$j"
    done
done

相關主題