5.3.3 函数定义、参数与返回值
函数定义、参数与返回值#
函数用于封装可复用逻辑,提升脚本可读性与可维护性。Bash 函数无需声明类型,遵循“先定义后调用”的原则。
原理草图:函数调用与返回值流转#
1. 安装与环境准备(确保 Bash 支持)#
# Debian/Ubuntu
sudo apt-get update
sudo apt-get install -y bash
# RHEL/CentOS
sudo yum install -y bash
# 验证版本
bash --version
命令解释:
- apt-get/yum install bash:安装 Bash 解释器
- bash --version:查看版本,确认可用
2. 函数定义与调用(含参数与返回值)#
#!/usr/bin/env bash
# /tmp/func_demo.sh
# 函数定义:function 关键字可省略
sum() {
local a="$1"
local b="$2"
local result=$((a + b))
echo "$result" # 输出结果供调用方使用
return 0 # 返回状态码:0 表示成功
}
# 调用函数并获取输出
total="$(sum 3 5)"
echo "sum(3,5) = $total"
# 返回值(状态码)示例
check_dir() {
local dir="$1"
if [ -d "$dir" ]; then
return 0
else
return 1
fi
}
check_dir "/etc"
echo "check_dir /etc => $?" # 0 表示存在
check_dir "/noexist"
echo "check_dir /noexist => $?" # 1 表示不存在
命令解释:
- local:定义函数内局部变量,避免污染全局
- echo:输出值给调用方(命令替换获取)
- return:仅返回状态码(0-255),不可直接返回大数或字符串
- $?:获取上一条命令/函数返回状态码
3. 参数处理与默认值示例#
#!/usr/bin/env bash
# /tmp/param_demo.sh
greet() {
local name="${1:-world}" # 如果未传参,默认 world
local times="${2:-1}" # 默认执行 1 次
for ((i=1; i<=times; i++)); do
echo "Hello, $name ($i)"
done
}
greet
greet "linux" 3
命令解释:
- ${1:-world}:若 $1 为空,使用默认值
- for ((...)):C 风格循环
4. 排错与常见问题#
# 1) 语法错误:函数未定义即调用
./script.sh: line 5: foo: command not found
# 解决:确保 foo 函数在调用前定义
# 2) 返回值误用:return 传大数或字符串
return "ok"
# 解决:return 仅支持 0-255,返回字符串用 echo + 命令替换
# 3) 变量污染:未用 local
sum() { a=1; } # 可能覆盖全局变量 a
# 解决:使用 local a=1
5. 实战小示例:检查服务端口并返回状态#
#!/usr/bin/env bash
# /tmp/port_check.sh
check_port() {
local port="$1"
if ss -lnt | awk '{print $4}' | grep -q ":${port}$"; then
echo "port $port is listening"
return 0
else
echo "port $port is NOT listening"
return 1
fi
}
check_port 22
echo "status=$?"
命令解释:
- ss -lnt:列出 TCP 监听端口
- awk '{print $4}':提取本地地址列
- grep -q:安静模式,仅返回状态码
6. 练习#
- 编写函数
backup_file,输入文件路径,若存在则复制到/tmp/backup/并返回 0,否则返回 1。 - 编写函数
avg,输入多个数字(使用$@),输出平均值。 - 写一个脚本,调用
check_dir函数判断/var/log,若存在则统计日志文件数并输出。