函数返回值 #
一、return语句 #
1.1 基本用法 #
bash
#!/bin/bash
# 返回状态码
check_file() {
if [[ -f "$1" ]]; then
return 0 # 成功
else
return 1 # 失败
fi
}
# 使用返回值
if check_file "/etc/passwd"; then
echo "文件存在"
else
echo "文件不存在"
fi
# 获取返回值
check_file "/etc/passwd"
echo "返回状态: $?"
1.2 返回值含义 #
bash
#!/bin/bash
# 标准返回值
# 0 - 成功
# 1 - 一般错误
# 2 - 参数错误
# 其他 - 自定义错误码
validate_input() {
local input="$1"
# 检查参数
if [[ -z "$input" ]]; then
echo "错误: 输入为空" >&2
return 2 # 参数错误
fi
# 检查格式
if ! [[ "$input" =~ ^[0-9]+$ ]]; then
echo "错误: 输入不是数字" >&2
return 1 # 格式错误
fi
# 检查范围
if (( input < 1 || input > 100 )); then
echo "错误: 超出范围" >&2
return 3 # 范围错误
fi
return 0 # 成功
}
validate_input "50"
echo "状态: $?"
1.3 返回值限制 #
bash
#!/bin/bash
# return只能返回0-255的整数
test_return() {
return 300 # 会被截断为 300 % 256 = 44
}
test_return
echo "返回值: $?" # 输出: 44
# 返回负数
test_negative() {
return -1 # 会被转换为 255
}
test_negative
echo "返回值: $?" # 输出: 255
二、echo返回数据 #
2.1 返回字符串 #
bash
#!/bin/bash
# 返回字符串
get_greeting() {
local name="$1"
echo "你好, $name!"
}
message=$(get_greeting "张三")
echo "$message"
# 在条件中使用
if [[ $(get_greeting "张三") == *"张三"* ]]; then
echo "包含张三"
fi
2.2 返回计算结果 #
bash
#!/bin/bash
# 返回数字
add() {
local a=$1
local b=$2
echo $((a + b))
}
result=$(add 5 3)
echo "结果: $result"
# 返回浮点数
divide() {
local a=$1
local b=$2
if (( b == 0 )); then
echo "错误: 除数为0" >&2
return 1
fi
echo "scale=2; $a / $b" | bc
}
result=$(divide 10 3)
echo "结果: $result"
2.3 返回数组 #
bash
#!/bin/bash
# 返回数组
get_numbers() {
echo 1 2 3 4 5
}
numbers=($(get_numbers))
echo "数组: ${numbers[@]}"
echo "长度: ${#numbers[@]}"
# 返回多行数据
get_lines() {
echo "第一行"
echo "第二行"
echo "第三行"
}
# 读取到数组
mapfile -t lines < <(get_lines)
for line in "${lines[@]}"; do
echo "行: $line"
done
三、返回多个值 #
3.1 使用全局变量 #
bash
#!/bin/bash
# 使用全局变量返回多个值
get_user_info() {
USER_NAME="张三"
USER_AGE=25
USER_CITY="北京"
}
get_user_info
echo "姓名: $USER_NAME"
echo "年龄: $USER_AGE"
echo "城市: $USER_CITY"
3.2 使用echo多行 #
bash
#!/bin/bash
# 返回多行数据
get_user_info() {
echo "张三"
echo "25"
echo "北京"
}
# 读取到变量
{
read -r name
read -r age
read -r city
} < <(get_user_info)
echo "姓名: $name, 年龄: $age, 城市: $city"
# 或者使用数组
info=()
while IFS= read -r line; do
info+=("$line")
done < <(get_user_info)
echo "姓名: ${info[0]}, 年龄: ${info[1]}, 城市: ${info[2]}"
3.3 使用分隔符 #
bash
#!/bin/bash
# 使用分隔符返回
get_user_info() {
echo "张三:25:北京"
}
IFS=':' read -r name age city <<< "$(get_user_info)"
echo "姓名: $name, 年龄: $age, 城市: $city"
# 使用自定义分隔符
get_data() {
echo "apple|banana|cherry"
}
IFS='|' read -ra fruits <<< "$(get_data)"
echo "水果: ${fruits[@]}"
3.4 使用关联数组 #
bash
#!/bin/bash
# 返回关联数组
get_user_info() {
declare -A user
user[name]="张三"
user[age]=25
user[city]="北京"
# 输出键值对
for key in "${!user[@]}"; do
echo "$key=${user[$key]}"
done
}
# 读取到关联数组
declare -A result
while IFS='=' read -r key value; do
result["$key"]="$value"
done < <(get_user_info)
echo "姓名: ${result[name]}"
echo "年龄: ${result[age]}"
echo "城市: ${result[city]}"
四、返回值与错误处理 #
4.1 结合return和echo #
bash
#!/bin/bash
# 同时返回状态和数据
get_file_info() {
local file="$1"
# 检查文件
if [[ ! -f "$file" ]]; then
echo "文件不存在" >&2
return 1
fi
# 返回文件信息
local size=$(stat -c %s "$file")
local perms=$(stat -c %a "$file")
local owner=$(stat -c %U "$file")
echo "$size:$perms:$owner"
return 0
}
# 使用示例
if info=$(get_file_info "/etc/passwd"); then
IFS=':' read -r size perms owner <<< "$info"
echo "大小: $size, 权限: $perms, 所有者: $owner"
else
echo "获取文件信息失败"
fi
4.2 错误处理模式 #
bash
#!/bin/bash
# 完整的错误处理
process_file() {
local file="$1"
local output="$2"
# 参数验证
if [[ -z "$file" ]]; then
echo "错误: 文件参数为空" >&2
return 2
fi
if [[ -z "$output" ]]; then
echo "错误: 输出参数为空" >&2
return 2
fi
# 文件检查
if [[ ! -f "$file" ]]; then
echo "错误: 文件不存在: $file" >&2
return 1
fi
if [[ ! -r "$file" ]]; then
echo "错误: 文件不可读: $file" >&2
return 1
fi
# 处理文件
if ! cp "$file" "$output"; then
echo "错误: 复制文件失败" >&2
return 1
fi
echo "处理成功: $output"
return 0
}
# 调用并处理错误
case $(process_file "input.txt" "output.txt"; echo $?) in
0) echo "完成" ;;
1) echo "处理错误" ;;
2) echo "参数错误" ;;
esac
五、实战示例 #
5.1 数据库查询函数 #
bash
#!/bin/bash
# 查询用户
query_user() {
local user_id="$1"
# 模拟数据库查询
case "$user_id" in
1)
echo "张三:25:北京"
return 0
;;
2)
echo "李四:30:上海"
return 0
;;
*)
echo "用户不存在" >&2
return 1
;;
esac
}
# 使用示例
if data=$(query_user 1); then
IFS=':' read -r name age city <<< "$data"
echo "查询结果: $name, $age岁, $city"
fi
5.2 API请求函数 #
bash
#!/bin/bash
# HTTP请求函数
http_request() {
local method="$1"
local url="$2"
local data="${3:-}"
local response
local http_code
# 发送请求
if [[ -n "$data" ]]; then
response=$(curl -s -w "\n%{http_code}" -X "$method" -d "$data" "$url")
else
response=$(curl -s -w "\n%{http_code}" -X "$method" "$url")
fi
http_code=$(echo "$response" | tail -n 1)
response=$(echo "$response" | sed '$d')
# 返回结果
echo "$http_code:$response"
# 根据HTTP状态码返回
if [[ "$http_code" =~ ^2[0-9]{2}$ ]]; then
return 0
else
return 1
fi
}
# 使用示例
result=$(http_request "GET" "https://api.example.com/users")
code="${result%%:*}"
body="${result#*:}"
if [[ "$code" == "200" ]]; then
echo "响应: $body"
else
echo "请求失败: HTTP $code"
fi
5.3 文件处理函数 #
bash
#!/bin/bash
# 分析文件
analyze_file() {
local file="$1"
# 验证文件
if [[ ! -f "$file" ]]; then
echo "文件不存在" >&2
return 1
fi
# 收集信息
local lines=$(wc -l < "$file")
local words=$(wc -w < "$file")
local chars=$(wc -c < "$file")
local size=$(du -h "$file" | cut -f1)
# 返回JSON格式
cat << EOF
{
"file": "$file",
"lines": $lines,
"words": $words,
"chars": $chars,
"size": "$size"
}
EOF
return 0
}
# 使用示例
if result=$(analyze_file "script.sh"); then
echo "$result" | jq '.'
fi
六、返回值最佳实践 #
6.1 一致的返回模式 #
bash
#!/bin/bash
# 推荐:成功返回数据,失败输出错误
process_data() {
local data="$1"
if [[ -z "$data" ]]; then
echo "错误: 数据为空" >&2
return 1
fi
# 处理数据
local result="${data^^}" # 转大写
echo "$result"
return 0
}
# 不推荐:混合使用
bad_function() {
if [[ -z "$1" ]]; then
echo "错误" # 应该输出到stderr
return 1
fi
echo "成功"
}
6.2 文档化返回值 #
bash
#!/bin/bash
# 函数:验证用户输入
#
# 参数:
# $1 - 用户输入
#
# 返回:
# 成功:返回处理后的数据
# 失败:输出错误信息到stderr,返回非零状态码
#
# 状态码:
# 0 - 成功
# 1 - 输入为空
# 2 - 输入格式错误
# 3 - 输入范围错误
#
validate_input() {
local input="$1"
[[ -z "$input" ]] && { echo "错误: 输入为空" >&2; return 1; }
[[ ! "$input" =~ ^[0-9]+$ ]] && { echo "错误: 格式错误" >&2; return 2; }
(( input < 1 || input > 100 )) && { echo "错误: 范围错误" >&2; return 3; }
echo "$input"
return 0
}
七、总结 #
7.1 返回值方式对比 #
| 方式 | 用途 | 示例 |
|---|---|---|
| return | 返回状态码 | return 0 |
| echo | 返回数据 | echo “data” |
| 全局变量 | 返回多个值 | RESULT=“value” |
| 关联数组 | 返回键值对 | declare -A result |
7.2 下一步 #
你已经掌握了函数返回值,接下来让我们学习 变量作用域,了解变量的作用范围!
最后更新:2026-03-27