Skip to content

函数参数

位置参数

基本用法

bash
#!/bin/bash

# 定义函数
greet() {
    echo "Hello, $1!"
    echo "你的年龄是: $2"
}

# 调用函数
greet "张三" 25

访问所有参数

bash
#!/bin/bash

# 定义函数
print_all_args() {
    echo "所有参数: $@"
    echo "参数个数: $#"
}

# 调用函数
print_all_args "apple" "banana" "orange"

遍历参数

bash
#!/bin/bash

# 定义函数
print_args() {
    echo "参数个数: $#"
    for arg in "$@"; do
        echo "参数: $arg"
    done
}

# 调用函数
print_args "a" "b" "c" "d"

特殊参数

$@ 和 $*

bash
#!/bin/bash

# 定义函数
test_special_params() {
    echo "使用 \$@:"
    for arg in "$@"; do
        echo "  $arg"
    done
    
    echo "使用 \$*:"
    for arg in "$*"; do
        echo "  $arg"
    done
}

# 调用函数
test_special_params "a b" "c d"

$#

bash
#!/bin/bash

# 定义函数
count_args() {
    echo "参数个数: $#"
}

# 调用函数
count_args "a" "b" "c"
count_args

$0

bash
#!/bin/bash

# 定义函数
show_script_name() {
    echo "脚本名称: $0"
}

# 调用函数
show_script_name

默认参数

设置默认值

bash
#!/bin/bash

# 定义带默认参数的函数
greet() {
    local name=${1:-"World"}
    echo "Hello, $name!"
}

# 调用函数
greet "张三"
greet

多个默认参数

bash
#!/bin/bash

# 定义带多个默认参数的函数
create_file() {
    local filename=${1:-"default.txt"}
    local content=${2:-"默认内容"}
    
    echo "$content" > "$filename"
    echo "文件创建成功: $filename"
}

# 调用函数
create_file "test.txt" "测试内容"
create_file

参数验证

检查参数数量

bash
#!/bin/bash

# 定义带参数验证的函数
add() {
    if [ $# -ne 2 ]; then
        echo "错误: 需要 2 个参数"
        return 1
    fi
    echo $(($1 + $2))
}

# 调用函数
result=$(add 10 20)
echo "10 + 20 = $result"

result=$(add 10)
echo "10 = $result"

检查参数类型

bash
#!/bin/bash

# 定义带参数类型检查的函数
is_number() {
    local num="$1"
    [[ "$num" =~ ^-?[0-9]+$ ]]
}

# 定义函数
multiply() {
    if ! is_number "$1" || ! is_number "$2"; then
        echo "错误: 参数必须是数字"
        return 1
    fi
    echo $(($1 * $2))
}

# 调用函数
result=$(multiply 10 20)
echo "10 * 20 = $result"

result=$(multiply "a" "b")
echo "a * b = $result"

检查参数是否为空

bash
#!/bin/bash

# 定义带空值检查的函数
print_upper() {
    if [ -z "$1" ]; then
        echo "错误: 参数不能为空"
        return 1
    fi
    echo "$1" | tr '[:lower:]' '[:upper:]'
}

# 调用函数
result=$(print_upper "hello")
echo "hello -> $result"

result=$(print_upper "")
echo " -> $result"

命名参数

使用关联数组

bash
#!/bin/bash

# 定义使用命名参数的函数
create_user() {
    local -A params
    params["name"]="$1"
    params["age"]="$2"
    params["city"]="$3"
    
    echo "姓名: ${params["name"]}"
    echo "年龄: ${params["age"]}"
    echo "城市: ${params["city"]}"
}

# 调用函数
create_user "张三" 25 "北京"

解析命名参数

bash
#!/bin/bash

# 定义解析命名参数的函数
parse_args() {
    while [ $# -gt 0 ]; do
        case "$1" in
            --name=*)
                name="${1#*=}"
                ;;
            --age=*)
                age="${1#*=}"
                ;;
            --city=*)
                city="${1#*=}"
                ;;
            *)
                echo "未知参数: $1"
                return 1
                ;;
        esac
        shift
    done
    
    echo "姓名: $name"
    echo "年龄: $age"
    echo "城市: $city"
}

# 调用函数
parse_args --name="张三" --age=25 --city="北京"

可变参数

处理可变数量的参数

bash
#!/bin/bash

# 定义处理可变参数的函数
sum() {
    local total=0
    for num in "$@"; do
        total=$((total + num))
    done
    echo $total
}

# 调用函数
result=$(sum 1 2 3 4 5)
echo "1 + 2 + 3 + 4 + 5 = $result"

result=$(sum 10 20 30)
echo "10 + 20 + 30 = $result"

混合固定参数和可变参数

bash
#!/bin/bash

# 定义混合参数的函数
concat() {
    local separator="$1"
    shift
    local result=""
    
    for item in "$@"; do
        if [ -z "$result" ]; then
            result="$item"
        else
            result="$result$separator$item"
        fi
    done
    
    echo "$result"
}

# 调用函数
result=$(concat "-" "a" "b" "c" "d")
echo "结果: $result"

参数数组

传递数组

bash
#!/bin/bash

# 定义接收数组的函数
process_array() {
    local arr=("$@")
    echo "数组长度: ${#arr[@]}"
    
    for item in "${arr[@]}"; do
        echo "  $item"
    done
}

# 调用函数
my_array=("apple" "banana" "orange")
process_array "${my_array[@]}"

返回数组

bash
#!/bin/bash

# 定义返回数组的函数
get_fruits() {
    local fruits=("apple" "banana" "orange")
    echo "${fruits[@]}"
}

# 调用函数
fruits=($(get_fruits))
echo "水果列表:"
for fruit in "${fruits[@]}"; do
    echo "  $fruit"
done

实用示例

示例1:文件操作函数

bash
#!/bin/bash

# 创建文件
create_file() {
    local filename="$1"
    local content="$2"
    
    if [ -z "$filename" ]; then
        echo "错误: 文件名不能为空"
        return 1
    fi
    
    echo "${content:-默认内容}" > "$filename"
    echo "文件创建成功: $filename"
}

# 删除文件
delete_file() {
    local filename="$1"
    
    if [ -z "$filename" ]; then
        echo "错误: 文件名不能为空"
        return 1
    fi
    
    if [ ! -f "$filename" ]; then
        echo "错误: 文件不存在: $filename"
        return 1
    fi
    
    rm "$filename"
    echo "文件删除成功: $filename"
}

# 使用函数
create_file "test.txt" "测试内容"
delete_file "test.txt"

示例2:字符串处理函数

bash
#!/bin/bash

# 字符串拼接
concat() {
    local separator="$1"
    shift
    local result=""
    
    for item in "$@"; do
        if [ -z "$result" ]; then
            result="$item"
        else
            result="$result$separator$item"
        fi
    done
    
    echo "$result"
}

# 字符串查找
find_string() {
    local string="$1"
    local substring="$2"
    
    if [[ "$string" == *"$substring"* ]]; then
        return 0
    else
        return 1
    fi
}

# 使用函数
result=$(concat "-" "a" "b" "c")
echo "拼接结果: $result"

if find_string "hello world" "world"; then
    echo "找到子串"
else
    echo "未找到子串"
fi

示例3:数学运算函数

bash
#!/bin/bash

# 加法
add() {
    echo $(($1 + $2))
}

# 减法
subtract() {
    echo $(($1 - $2))
}

# 乘法
multiply() {
    echo $(($1 * $2))
}

# 除法
divide() {
    if [ $2 -eq 0 ]; then
        echo "错误: 除数不能为 0"
        return 1
    fi
    echo $(($1 / $2))
}

# 使用函数
result=$(add 10 20)
echo "10 + 20 = $result"

result=$(subtract 20 10)
echo "20 - 10 = $result"

result=$(multiply 10 20)
echo "10 * 20 = $result"

result=$(divide 20 10)
echo "20 / 10 = $result"

示例4:日志函数

bash
#!/bin/bash

# 日志函数
log() {
    local level="$1"
    shift
    local message="$@"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] [$level] $message"
}

# 信息日志
info() {
    log "INFO" "$@"
}

# 警告日志
warn() {
    log "WARN" "$@"
}

# 错误日志
error() {
    log "ERROR" "$@"
}

# 使用函数
info "程序启动"
warn "配置文件不存在"
error "连接失败"

最佳实践

1. 验证参数

bash
# 好的做法
func() {
    if [ $# -lt 1 ]; then
        echo "错误: 缺少参数"
        return 1
    fi
    echo "$1"
}

# 不好的做法
func() {
    echo "$1"
}

2. 使用默认值

bash
# 好的做法
func() {
    local param=${1:-"默认值"}
    echo "$param"
}

# 不好的做法
func() {
    local param="$1"
    if [ -z "$param" ]; then
        param="默认值"
    fi
    echo "$param"
}

3. 使用引号

bash
# 好的做法
func() {
    for arg in "$@"; do
        echo "$arg"
    done
}

# 不好的做法
func() {
    for arg in $@; do
        echo $arg
    done
}

总结

函数参数的关键点:

  1. 位置参数$1, $2, $3, ...
  2. 特殊参数$@, $*, $#, $0
  3. 默认参数${param:-"默认值"}
  4. 参数验证:检查数量、类型、是否为空
  5. 命名参数:使用关联数组或解析参数
  6. 可变参数:处理可变数量的参数
  7. 参数数组:传递和返回数组

下一节我们将学习函数作用域的使用。