16.shell编程-函数
学习 Shell 函数(function) 是从“写脚本”迈向“写程序”的关键一步,掌握函数后,你就能让脚本模块化、可复用、可维护,就像在 C / Python 里写函数一样。
下面我们系统地讲一遍:
📘 定义语法 → 参数传递 → 返回值 → 作用域 → 高级用法 → 实战示例。
🧩 一、什么是 Shell 函数?
函数(Function)就是一段可复用的脚本代码,用来完成特定任务。
写一次,可以多次调用。
它让脚本结构更清晰,更容易维护。
⚙️ 二、函数定义语法
在 Shell(如 bash
)中,有两种等价写法:
# 写法1(推荐)
function 函数名 {命令序列
}# 写法2(更通用)
函数名() {命令序列
}
👉 注意:
function
关键字可省略。{}
内的命令与普通 Shell 命令一样执行。- 定义函数时不能在同一行加
()
参数(不像 Python/C)。
🧠 三、简单示例
#!/bin/bashsay_hello() {echo "Hello, Shell!"
}say_hello
say_hello
输出:
Hello, Shell!
Hello, Shell!
✅ 执行时,Shell 会先加载整个脚本的函数定义,然后再按调用顺序执行。
🧮 四、函数参数传递
函数的参数使用 $1
、$2
、…、$9
表示,
与脚本自身的参数机制一致。
示例:
#!/bin/bashgreet() {echo "Hello, $1!"echo "Today is $2."
}greet "Alice" "Friday"
输出:
Hello, Alice!
Today is Friday.
常用参数变量
变量 | 含义 |
---|---|
$0 | 脚本名(不是函数名) |
$1 ~$9 | 函数的前9个参数 |
$# | 参数个数 |
$@ | 所有参数(分开显示) |
$* | 所有参数(整体显示) |
"$@" | 保留参数间空格的安全写法 |
示例:遍历所有参数
print_args() {echo "参数个数: $#"for arg in "$@"; doecho "参数: $arg"done
}print_args apple banana "hello world"
输出:
参数个数: 3
参数: apple
参数: banana
参数: hello world
🔁 五、返回值机制
函数执行后,可用 $?
查看返回状态码(0 表示成功,非0表示错误)。
is_root() {if [ "$EUID" -eq 0 ]; thenreturn 0elsereturn 1fi
}is_root
if [ $? -eq 0 ]; thenecho "你是 root 用户"
elseecho "你不是 root 用户"
fi
自定义返回值
return
语句可以返回 0–255 的整数:
sum() {return $(($1 + $2))
}sum 3 5
echo "返回值: $?" # 输出 8
⚠️ 限制:
return
只能返回整数(0–255),
如果要返回字符串或更复杂结果 → 用 echo
+ 命令替换。
返回字符串(推荐做法)
get_name() {echo "Alice"
}name=$(get_name)
echo "Hello, $name!"
🧱 六、作用域(变量可见性)
默认情况下,Shell 变量是全局的。
要让变量只在函数内有效,需使用 local
。
#!/bin/bash
foo="global"test_func() {local foo="local"echo "函数内: $foo"
}test_func
echo "函数外: $foo"
输出:
函数内: local
函数外: global
⚡ 七、嵌套函数与函数调用顺序
函数可以在函数里调用其他函数:
add() {echo $(($1 + $2))
}sum_and_double() {local sum=$(add $1 $2)echo $(($sum * 2))
}sum_and_double 3 4 # 输出 14
🧰 八、带条件的函数调用
log_info() {echo "[INFO] $1"
}log_error() {echo "[ERROR] $1"
}if [ "$1" == "error" ]; thenlog_error "Something went wrong!"
elselog_info "All good."
fi
🧩 九、函数库(模块化脚本)
你可以把函数写到单独文件中,然后用 source
或 .
引入。
例如:
文件:utils.sh
say_hi() {echo "Hi, $1"
}
主脚本:
#!/bin/bash
source utils.sh
say_hi "Bob"
输出:
Hi, Bob
🧮 十、实战例子:系统健康检测函数
#! /bin/bashcheck_cpu() {usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2 + $4}')echo "CPU使用率: $usage%"
}check_mem() {free -h | awk '/Mem/ {print "内存使用: "$3 "/" $2}'
}check_disk() {df -h | awk '$NF=="/"{print "磁盘使用: "$5}'
}system_report() {echo "=== 系统状态报告 ==="check_cpucheck_memcheck_disk
}system_report
输出示例:
=== 系统状态报告 ===
CPU使用率: 15.3%
内存使用: 2.5G/8G
磁盘使用: 67%
🧠 十一、总结速查表
功能 | 示例 | 说明 |
---|---|---|
定义函数 | f() { echo hi; } | 两种写法都行 |
调用函数 | f | 直接写名字 |
传递参数 | $1 , $2 , … | 与脚本参数机制相同 |
参数个数 | $# | 统计参数数量 |
所有参数 | "$@" | 保留空格最安全 |
返回值 | return N / echo | 数值用 return,字符串用 echo |
局部变量 | local var=value | 仅函数内部有效 |
引用库函数 | source file.sh | 导入函数文件 |
🧩 十二、进阶:匿名函数(间接调用)
虽然 Shell 不支持“真正匿名函数”,
但可以通过变量名间接调用函数:
say_hi() { echo "Hi, $1"; }func_name="say_hi"
$func_name "Bob"
输出:
Hi, Bob