函数参数 #
一、位置参数 #
1.1 基本用法 #
bash
#!/bin/bash
show_params() {
echo "第一个参数: $1"
echo "第二个参数: $2"
echo "第三个参数: $3"
echo "所有参数: $@"
echo "参数个数: $#"
}
show_params "apple" "banana" "cherry"
1.2 参数访问 #
bash
#!/bin/bash
access_params() {
# 访问单个参数
echo "第一个: $1"
echo "第二个: $2"
# 访问所有参数
echo "所有参数: $*"
echo "所有参数: $@"
# 参数个数
echo "参数数量: $#"
# 脚本名(在函数中仍然是脚本名)
echo "脚本名: $0"
}
access_params "one" "two" "three"
1.3 $* 与 $@ 的区别 #
bash
#!/bin/bash
test_difference() {
echo "使用 \$* 遍历:"
for arg in "$*"; do
echo " 参数: [$arg]"
done
echo "使用 \$@ 遍历:"
for arg in "$@"; do
echo " 参数: [$arg]"
done
}
test_difference "a b" "c d" "e"
二、参数处理 #
2.1 默认参数 #
bash
#!/bin/bash
greet() {
local name="${1:-匿名}"
local greeting="${2:-你好}"
echo "$greeting, $name!"
}
greet "张三" "早上好"
greet "李四"
greet
2.2 使用shift处理参数 #
bash
#!/bin/bash
process_options() {
local verbose=false
local output=""
while [[ $# -gt 0 ]]; do
case "$1" in
-v|--verbose)
verbose=true
shift
;;
-o|--output)
output="$2"
shift 2
;;
-h|--help)
echo "用法: 函数名 [选项]"
echo " -v, --verbose 详细输出"
echo " -o, --output 输出文件"
return 0
;;
--)
shift
break
;;
*)
echo "未知选项: $1"
shift
;;
esac
done
echo "详细模式: $verbose"
echo "输出文件: ${output:-标准输出}"
echo "剩余参数: $@"
}
process_options -v -o result.txt file1 file2
2.3 参数数组 #
bash
#!/bin/bash
# 传递数组
process_array() {
local arr=("$@")
echo "数组元素:"
for item in "${arr[@]}"; do
echo " $item"
done
echo "数组长度: ${#arr[@]}"
}
fruits=("苹果" "香蕉" "橙子")
process_array "${fruits[@]}"
# 返回数组
get_numbers() {
local result=(1 2 3 4 5)
echo "${result[@]}"
}
numbers=($(get_numbers))
echo "获取的数组: ${numbers[@]}"
三、参数验证 #
3.1 基本验证 #
bash
#!/bin/bash
validate_basic() {
# 检查参数数量
if [[ $# -lt 1 ]]; then
echo "错误: 至少需要一个参数" >&2
return 1
fi
# 检查参数非空
if [[ -z "$1" ]]; then
echo "错误: 参数不能为空" >&2
return 1
fi
echo "参数验证通过: $1"
return 0
}
validate_basic "test"
validate_basic ""
validate_basic
3.2 类型验证 #
bash
#!/bin/bash
# 验证数字
is_number() {
[[ "$1" =~ ^[0-9]+$ ]]
}
# 验证整数
is_integer() {
[[ "$1" =~ ^-?[0-9]+$ ]]
}
# 验证浮点数
is_float() {
[[ "$1" =~ ^-?[0-9]+(\.[0-9]+)?$ ]]
}
# 验证邮箱
is_email() {
[[ "$1" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]
}
# 使用验证
validate_input() {
local input="$1"
local type="$2"
case "$type" in
number)
if ! is_number "$input"; then
echo "错误: $input 不是有效数字" >&2
return 1
fi
;;
integer)
if ! is_integer "$input"; then
echo "错误: $input 不是有效整数" >&2
return 1
fi
;;
float)
if ! is_float "$input"; then
echo "错误: $input 不是有效浮点数" >&2
return 1
fi
;;
email)
if ! is_email "$input"; then
echo "错误: $input 不是有效邮箱" >&2
return 1
fi
;;
*)
echo "错误: 未知验证类型 $type" >&2
return 1
;;
esac
echo "验证通过"
return 0
}
validate_input "123" "number"
validate_input "3.14" "float"
validate_input "test@example.com" "email"
3.3 范围验证 #
bash
#!/bin/bash
validate_range() {
local value="$1"
local min="$2"
local max="$3"
# 验证是否为数字
if ! [[ "$value" =~ ^-?[0-9]+$ ]]; then
echo "错误: $value 不是有效数字" >&2
return 1
fi
# 验证范围
if (( value < min || value > max )); then
echo "错误: $value 不在范围 [$min, $max] 内" >&2
return 1
fi
echo "验证通过: $value"
return 0
}
validate_range 50 1 100
validate_range 150 1 100
四、高级参数处理 #
4.1 命名参数 #
bash
#!/bin/bash
# 使用命名参数
process_named_args() {
local name=""
local age=""
local city=""
while [[ $# -gt 0 ]]; do
case "$1" in
name=*)
name="${1#name=}"
shift
;;
age=*)
age="${1#age=}"
shift
;;
city=*)
city="${1#city=}"
shift
;;
*)
echo "未知参数: $1"
shift
;;
esac
done
echo "姓名: ${name:-未指定}"
echo "年龄: ${age:-未指定}"
echo "城市: ${city:-未指定}"
}
process_named_args name=张三 age=25 city=北京
4.2 参数解析函数 #
bash
#!/bin/bash
# 通用参数解析
parse_args() {
local -n result=$1 # 使用名称引用(Bash 4.3+)
shift
while [[ $# -gt 0 ]]; do
local key="${1%%=*}"
local value="${1#*=}"
if [[ "$1" == *=* ]]; then
result["$key"]="$value"
else
result["_args"]+=" $1"
fi
shift
done
}
# 使用示例
declare -A args
parse_args args name=张三 age=25 file.txt
echo "姓名: ${args[name]}"
echo "年龄: ${args[age]}"
echo "其他参数: ${args[_args]}"
4.3 参数传递给其他函数 #
bash
#!/bin/bash
# 包装函数
wrapper() {
echo "包装函数处理..."
inner "$@"
}
inner() {
echo "内部函数收到参数: $@"
}
wrapper "a" "b" "c"
# 过滤参数后传递
filter_and_pass() {
local filtered=()
while [[ $# -gt 0 ]]; do
if [[ "$1" != "--skip" ]]; then
filtered+=("$1")
fi
shift
done
process "${filtered[@]}"
}
process() {
echo "处理: $@"
}
filter_and_pass "a" "--skip" "b" "c"
五、实战示例 #
5.1 配置文件解析 #
bash
#!/bin/bash
parse_config() {
local config_file="$1"
local -n config_ref=$2
if [[ ! -f "$config_file" ]]; then
echo "错误: 配置文件不存在" >&2
return 1
fi
while IFS='=' read -r key value || [[ -n "$key" ]]; do
# 跳过注释和空行
[[ "$key" =~ ^#.*$ ]] && continue
[[ -z "$key" ]] && continue
# 去除前后空格
key=$(echo "$key" | xargs)
value=$(echo "$value" | xargs)
config_ref["$key"]="$value"
done < "$config_file"
}
# 使用示例
declare -A config
parse_config "app.conf" config
echo "数据库: ${config[database]}"
echo "端口: ${config[port]}"
5.2 命令行工具函数 #
bash
#!/bin/bash
# 命令行参数解析
parse_cli() {
local action=""
local files=()
local options=()
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
show_help
exit 0
;;
-v|--version)
echo "版本: 1.0.0"
exit 0
;;
-o=*|--option=*)
options+=("${1#*=}")
shift
;;
-*)
echo "未知选项: $1" >&2
exit 1
;;
*)
if [[ -z "$action" ]]; then
action="$1"
else
files+=("$1")
fi
shift
;;
esac
done
# 返回解析结果
ACTION="$action"
FILES=("${files[@]}")
OPTIONS=("${options[@]}")
}
show_help() {
cat << EOF
用法: $0 [选项] <动作> [文件...]
选项:
-h, --help 显示帮助
-v, --version 显示版本
-o, --option 设置选项
动作:
process 处理文件
validate 验证文件
convert 转换文件
EOF
}
# 使用示例
parse_cli "$@"
echo "动作: $ACTION"
echo "文件: ${FILES[@]}"
echo "选项: ${OPTIONS[@]}"
5.3 参数验证工具 #
bash
#!/bin/bash
# 参数验证器
validate_args() {
local rules=("$@")
local errors=()
for rule in "${rules[@]}"; do
local param="${rule%%:*}"
local type="${rule#*:}"
local value="${!param}"
case "$type" in
required)
if [[ -z "$value" ]]; then
errors+=("$param 是必需的")
fi
;;
number)
if [[ -n "$value" ]] && ! [[ "$value" =~ ^[0-9]+$ ]]; then
errors+=("$param 必须是数字")
fi
;;
email)
if [[ -n "$value" ]] && ! [[ "$value" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
errors+=("$param 必须是有效邮箱")
fi
;;
file)
if [[ -n "$value" ]] && [[ ! -f "$value" ]]; then
errors+=("$param 文件不存在")
fi
;;
esac
done
if [[ ${#errors[@]} -gt 0 ]]; then
for error in "${errors[@]}"; do
echo "错误: $error" >&2
done
return 1
fi
return 0
}
# 使用示例
NAME="张三"
AGE="25"
EMAIL="test@example.com"
validate_args \
"NAME:required" \
"AGE:number" \
"EMAIL:email"
六、参数处理最佳实践 #
6.1 使用帮助函数 #
bash
#!/bin/bash
show_usage() {
cat << EOF
用法: ${FUNCNAME[1]} [选项] <参数>
参数:
参数1 第一个参数说明
参数2 第二个参数说明
选项:
-h 显示帮助
-v 详细模式
示例:
${FUNCNAME[1]} -v arg1 arg2
EOF
}
my_function() {
if [[ "$1" == "-h" ]]; then
show_usage
return 0
fi
# 函数逻辑
}
6.2 参数文档化 #
bash
#!/bin/bash
# 函数:处理文件
#
# 参数:
# $1 - 文件路径(必需)
# $2 - 处理模式(可选,默认:read)
# $3 - 输出文件(可选)
#
# 返回:
# 0 - 成功
# 1 - 失败
#
# 示例:
# process_file "/path/to/file" "write" "output.txt"
#
process_file() {
local file="${1:?错误: 文件路径是必需的}"
local mode="${2:-read}"
local output="${3:-}"
# 函数实现
echo "处理文件: $file"
echo "模式: $mode"
[[ -n "$output" ]] && echo "输出: $output"
}
七、总结 #
7.1 参数处理要点 #
| 要点 | 说明 |
|---|---|
| 位置参数 | $1, $2, …, $@, $# |
| 默认值 | $ |
| 参数验证 | 检查数量、类型、范围 |
| shift | 移动参数位置 |
| 命名参数 | key=value 格式 |
7.2 下一步 #
你已经掌握了函数参数,接下来让我们学习 函数返回值,了解函数的返回值处理!
最后更新:2026-03-27