Shell 函数是脚本中封装可重用代码块的核心工具,可提升代码模块化、可读性和维护性。以下是关键知识点及操作示例(基于 Bash):
⚙️ 一、定义与调用
定义方式
- 标准语法(推荐)
function_name() { command1 command2 }
# 示例:打印欢迎信息 greet() { echo "Hello, $1!" }
- 使用
function
关键字function greet { echo "Hello, $1!" }
调用函数
greet "Alice" # 输出:Hello, Alice!
📥 二、参数传递
访问参数
- 位置参数:
$1
(第一个参数)、$2
(第二个)等 - 特殊变量:
$#
:参数个数$@
:所有参数的独立列表$*
:所有参数合并为单个字符串
sum() {
echo "参数个数: $#"
echo "参数列表: ${@}"
result=$(( $1 + $2 ))
echo "结果: $result"
}
sum 10 20 # 输出:参数个数:2 参数列表:10 20 结果:30
默认参数
# 若未传参则使用默认值
print_msg() {
local msg=${1:-"默认消息"}
echo "$msg"
}
print_msg # 输出:默认消息
print_msg "Hi" # 输出:Hi
🔄 三、返回值处理
两种返回值方式
方式 | 说明 | 示例 |
---|---|---|
return | 返回整数状态码(0-255),通过 $? 获取 | |
echo | 输出任意数据,通过 $(函数) 捕获结果 |
示例对比:
# 方式1:return(适合状态码)
is_even() {
if (( $1 % 2 == 0 )); then
return 0 # 成功
else
return 1 # 失败
fi
}
is_even 4; echo $? # 输出:0
# 方式2:echo(适合返回数据)
calc_square() {
echo $(( $1 ** 2 ))
}
result=$(calc_square 5) # 捕获输出
echo "平方值: $result" # 输出:25
🔍 四、变量作用域
- 全局变量:默认所有变量全局有效
count=0 increment() { ((count++)); } increment; echo $count # 输出:1
- 局部变量:用
local
限制作用域demo() { local var="内部变量" echo "函数内: $var" } demo; echo "函数外: $var" # 输出:函数内: 内部变量 函数外: (空)
🔁 五、进阶技巧
1. 递归函数
# 计算阶乘
factorial() {
if (( $1 <= 1 )); then
echo 1
else
local prev=$(factorial $(( $1 - 1 )))
echo $(( $1 * prev ))
fi
}
echo "5! = $(factorial 5)" # 输出:120
2. 函数库
创建库文件 math_lib.sh
:
add() { echo $(( $1 + $2 )); }
multiply() { echo $(( $1 * $2 )); }
主脚本调用:
source math_lib.sh
result=$(add 3 4) # 输出:7
3. 处理数组参数
# 将数组元素展开为多个参数
print_array() {
for item in "$@"; do
echo "元素: $item"
done
}
arr=("A" "B" "C")
print_array "${arr[@]}" # 正确传递数组
⚠️ 六、注意事项
- 参数限制:
- 超过9个参数需用
${10}
格式 - 含空格的参数需加引号:
func "arg with space"
- 超过9个参数需用
- 返回值陷阱:
return
仅支持 0-255 整数,超出值会取模(如 256→0)$?
仅保存最近一条命令的退出状态
- 关联数组函数:需 Bash 4.0+ 并声明
declare -A
💎 总结
功能 | 语法 | 关键点 |
---|---|---|
定义函数 | func() { ... } | 省略 function 时括号不可省 |
参数传递 | $1 , $@ , ${10} | 含空格参数需引号包裹 |
返回值 | return 状态码 或 echo 数据 | return 适合状态,echo 适合数据 |
局部变量 | local var=value | 避免污染全局作用域 |
关联数组需 Bash 4.0+(查看版本:
bash --version
)。实际脚本中建议多用函数封装逻辑,减少重复代码 。