函数返回值

Shell 函数的返回值和其他编程语言不太一样。return 返回的是退出状态码,不是数据本身。要想返回数据,得用其他方式。

return 语句

return 用于结束函数执行,并返回一个状态码:

check_file() {
    if [ -f "$1" ]; then
        return 0
    else
        return 1
    fi
}

check_file "/etc/passwd"
if [ $? -eq 0 ]; then
    echo "文件存在"
else
    echo "文件不存在"
fi

返回值范围是 0-255,0 表示成功,非 0 表示失败。如果不写 return,函数的返回值就是最后一条命令的退出状态。

获取返回值

$? 保存上一个命令或函数的返回值:

is_even() {
    if [ $(($1 % 2)) -eq 0 ]; then
        return 0
    else
        return 1
    fi
}

is_even 4
echo "返回值:$?"

is_even 7
echo "返回值:$?"

运行结果:

返回值:0
返回值:1

要注意 $? 只保存最近一次的返回值,用完就没了。如果需要多次使用,应该先保存起来:

is_even 10
result=$?
if [ $result -eq 0 ]; then
    echo "是偶数"
fi

返回字符串

return 只能返回数字,要返回字符串得用 echo 或 printf:

get_date() {
    date '+%Y-%m-%d'
}

today=$(get_date)
echo "今天是 $today"

函数内部 echo 的内容会被捕获到变量中。这种方式很常用,但要注意函数里不要有多余的输出:

get_full_name() {
    echo "调试信息:开始处理"  # 这行也会被捕获
    echo "$1 $2"
}

name=$(get_full_name "张" "三")
echo "姓名:$name"

运行结果:

姓名:调试信息:开始处理
张 三

调试信息混进去了,这是个常见的坑。调试信息应该输出到标准错误:

get_full_name() {
    echo "调试信息:开始处理" >&2
    echo "$1 $2"
}

这样调试信息会显示在屏幕上,但不会被 $() 捕获。

返回多个值

可以用数组或分隔符来返回多个值:

get_user_info() {
    echo "张三:25:北京"
}

info=$(get_user_info)
IFS=':' read -r name age city <<< "$info"
echo "姓名:$name,年龄:$age,城市:$city"

或者用数组:

get_numbers() {
    local arr=(1 2 3 4 5)
    echo "${arr[@]}"
}

result=$(get_numbers)
read -ra numbers <<< "$result"
echo "第一个数:${numbers[0]}"
echo "所有数:${numbers[@]}"

返回值和退出状态的区别

return 用于函数,exit 用于整个脚本。在函数里用 exit 会直接结束整个脚本:

test_func() {
    echo "函数开始"
    exit 0
    echo "这行不会执行"
}

echo "脚本开始"
test_func
echo "脚本结束"  # 这行也不会执行

运行结果:

脚本开始
函数开始

脚本直接退出了,后面的代码都没执行。要区分清楚:函数里用 return,脚本退出用 exit。

小结

  • return 返回 0-255 的状态码,0 表示成功
  • $? 获取返回值,要及时保存
  • 返回字符串用 echo,调试信息输出到 stderr
  • 返回多个值可以用分隔符或数组
  • 函数里用 return,不要用 exit