89. 函数、调试与综合示例
本教程共 90 篇 · 第 89 篇
89. 函数、调试与综合示例
脚本写长以后,把重复逻辑包成函数最省心。再学两招调试手段,出错时不抓瞎。
函数
函数把一串命令归到一个名字下,随叫随用。先定义后调用:
#!/bin/bash
greet() {
echo "你好,$1!"
}
greet 小明
greet 小红
函数里用 $1、$2 拿传给它的参数(和脚本参数一个道理)。想返回数字结果用 return,范围 0–255,靠 $? 取回:
add() {
return $(( $1 + $2 ))
}
add 3 4
echo "结果是 $?"
想返回普通文本,别用 return,直接 echo 出来再用 $() 接住。
局部变量
函数里用 local 声明变量,只在函数内有效,不会污染外面:
demo() {
local x=10
echo "函数内 x=$x"
}
demo
echo "函数外 x=${x:-未定义}"
不加 local 的变量是全局的,函数改了外面也跟着变,容易埋坑。
调试:set -x / set -e
set -x 把每条执行的命令和它展开后的参数打印出来,查错利器:
#!/bin/bash
set -x
name="小明"
echo "你好,$name"
set +x
set -e 让脚本”碰到任何命令失败就立刻退出”,防止错误被一路带下去:
#!/bin/bash
set -e
cd /some/path || exit 1
rm -rf ./build
Note
set -e有例外:写在if/while/until条件里、或&&/||链中(末尾命令除外)的失败,并不会触发退出。想要更严可写成set -euo pipefail(-u还会在用到未定义变量时报错)。
Warning脚本里用
rm -rf极度危险:变量若为空,rm -rf /$var会变成rm -rf /,删光整个系统。set -e只拦”命令失败”,拦不住”命令成功但删错了”——空变量时这条命令反而成功执行。务必先校验路径非空,例如写成rm -rf "${dir:?目录变量为空,已中止}",让 bash 在变量为空时直接报错退出。
综合示例:批量重命名
把当前目录 .txt 文件统一加 bak_ 前缀:
#!/bin/bash
set -e
for f in *.txt; do
[ -f "$f" ] || continue
mv "$f" "bak_$f"
echo "已重命名:$f -> bak_$f"
done
[ -f "$f" ] || continue 保证通配符没匹配到时跳过,避免对字面量 *.txt 误操作。
小结:函数复用代码,local 管住变量作用域,set -x 看过程、set -e 防雪崩。把前面学的串起来,就能写实用脚本了。