函数返回值 #

一、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