函式

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

Shell 函式定義、呼叫、參數傳遞與返回值。

函式定義

Shell 提供兩種函式定義語法:

# 語法 1(推薦)
function_name() {
    # 函式內容
}

# 語法 2
function function_name {
    # 函式內容
}

簡單範例

#!/bin/bash

# 定義函式
greet() {
    echo "Hello, World!"
}

# 呼叫函式
greet

參數傳遞

函式使用位置參數 $1, $2, $3 等接收參數:

greet() {
    local name=$1
    local age=$2
    echo "Hello, $name! You are $age years old."
}

# 呼叫函式
greet "Alice" 30
# 輸出: Hello, Alice! You are 30 years old.

參數相關變數

print_args() {
    echo "Function name: $0"
    echo "First arg: $1"
    echo "Second arg: $2"
    echo "All args: $@"
    echo "All args (quoted): $*"
    echo "Arg count: $#"
}

print_args apple banana cherry

$@ vs $*

demo() {
    # $@ - 每個參數作為獨立字串
    for arg in "$@"; do
        echo "[$arg]"
    done

    echo "---"

    # $* - 所有參數作為單一字串
    for arg in "$*"; do
        echo "[$arg]"
    done
}

demo "hello world" "foo" "bar"
# $@ 輸出:
# [hello world]
# [foo]
# [bar]
# $* 輸出:
# [hello world foo bar]

返回值

Shell 函式有兩種返回值方式:

return - 返回退出碼

is_even() {
    local num=$1
    if [ $((num % 2)) -eq 0 ]; then
        return 0  # 成功(真)
    else
        return 1  # 失敗(假)
    fi
}

# 使用
if is_even 4; then
    echo "Even"
else
    echo "Odd"
fi

# 或檢查 $?
is_even 5
if [ $? -eq 0 ]; then
    echo "Even"
else
    echo "Odd"
fi

注意: return 只能返回 0-255 的整數退出碼。

echo - 返回字串

get_full_name() {
    local first=$1
    local last=$2
    echo "${first} ${last}"
}

# 使用命令替換接收輸出
full_name=$(get_full_name "Alice" "Smith")
echo "Full name: $full_name"

組合使用

divide() {
    local a=$1
    local b=$2

    if [ $b -eq 0 ]; then
        echo "Error: Division by zero" >&2
        return 1
    fi

    echo $((a / b))
    return 0
}

# 使用
result=$(divide 10 2)
if [ $? -eq 0 ]; then
    echo "Result: $result"
else
    echo "Operation failed"
fi

局部變數 (local)

使用 local 宣告函式內的局部變數,避免污染全域命名空間:

global_var="I'm global"

test_scope() {
    local local_var="I'm local"
    global_var="Modified in function"

    echo "Inside function:"
    echo "  local_var: $local_var"
    echo "  global_var: $global_var"
}

echo "Before function:"
echo "  global_var: $global_var"
echo "  local_var: $local_var"  # 空值

test_scope

echo "After function:"
echo "  global_var: $global_var"  # 已被修改
echo "  local_var: $local_var"    # 仍為空

函式庫管理 (source)

將常用函式放入獨立檔案,使用 source. 載入:

# lib.sh
greet() {
    echo "Hello, $1!"
}

calculate_sum() {
    local sum=0
    for num in "$@"; do
        ((sum += num))
    done
    echo $sum
}
# main.sh
#!/bin/bash

# 載入函式庫
source ./lib.sh
# 或
# . ./lib.sh

# 使用載入的函式
greet "Alice"
result=$(calculate_sum 1 2 3 4 5)
echo "Sum: $result"

檢查函式是否已定義

if declare -f function_name > /dev/null; then
    echo "Function exists"
else
    echo "Function not found"
fi

遞迴函式

# 階乘
factorial() {
    local n=$1
    if [ $n -le 1 ]; then
        echo 1
    else
        local prev=$(factorial $((n - 1)))
        echo $((n * prev))
    fi
}

result=$(factorial 5)
echo "5! = $result"  # 120

費氏數列

fibonacci() {
    local n=$1
    if [ $n -le 1 ]; then
        echo $n
    else
        local a=$(fibonacci $((n - 1)))
        local b=$(fibonacci $((n - 2)))
        echo $((a + b))
    fi
}

# 輸出前 10 個費氏數
for i in {0..9}; do
    echo "F($i) = $(fibonacci $i)"
done

函式作為參數

# 高階函式:接受函式名稱作為參數
apply() {
    local func_name=$1
    shift  # 移除第一個參數
    $func_name "$@"  # 呼叫傳入的函式
}

double() {
    echo $(($ 1 * 2))
}

square() {
    echo $(($1 * $1))
}

# 使用
apply double 5    # 10
apply square 5    # 25

陣列與函式

# 傳遞陣列到函式
process_array() {
    local arr=("$@")  # 接收陣列
    for item in "${arr[@]}"; do
        echo "Processing: $item"
    done
}

fruits=("apple" "banana" "cherry")
process_array "${fruits[@]}"

函式返回陣列

# 使用全域變數返回陣列
get_even_numbers() {
    result=()  # 全域陣列
    for num in "$@"; do
        if [ $((num % 2)) -eq 0 ]; then
            result+=("$num")
        fi
    done
}

get_even_numbers 1 2 3 4 5 6 7 8
echo "Even numbers: ${result[@]}"

相關主題