跳到正文

bash 编程与脚本 ​

bash 不是“命令的集合”,而是一门完整语言:变量、条件、循环、函数、返回码都有。

返回码与短路 ​

  • 0 成功,非 0 失败,$? 是上一条命令的结果
  • && 成功才继续,|| 失败才执行
  • if、while 判断的是返回码
bash
mkdir /tmp/x && cd /tmp/x
grep -q pattern file && echo found

条件 ​

写法说明
[ -f file ]test 命令,方括号两侧要空格
[[ -f file ]]bash 语法,支持 &&、`
[ "$a" = "$b" ]字符串比较
[ "$n" -lt 10 ]数值比较
(( n++ ))算术展开

新脚本优先 [[ ]],它不会因为变量为空把语法拆坏。

位置参数 ​

变量含义
$0脚本名
$1…$9前九个参数
${10}第十个及以后
$#参数个数
$@全部参数
"$@"每个参数保持独立
shift丢掉第一个参数并左移

脚本骨架 ​

bash
#!/usr/bin/env bash
set -euo pipefail

log="run-$(date +%s).log"
while cargo test > "$log" 2>&1; do
  echo passed
done
tail -n 20 "$log"
部分作用
shebang指定解释器,env 会去 $PATH 找
set -e命令失败即退出
set -u未定义变量即退出
set -o pipefail管道任一段失败即失败
set -x打印展开后的命令

set -e 有边界:出现在 if 条件、&& 左值、! 后面的失败不会触发退出。

运行脚本 ​

bash
chmod +x script.sh
./script.sh
  • 当前目录默认不在 $PATH
  • bash script.sh 不需要可执行位,但会另起一个 Shell
  • source script.sh 在当前 Shell 执行
  • 权限位 755 = 所有者读写执行,其他人读执行

函数与后台 ​

bash
mkcd() { mkdir -p "$1" && cd "$1"; }
long_task & echo $!

函数里默认是全局变量,要局部写 local。

脚本超过一百行、需要数据结构和错误处理时,换 Python 更省事。shellcheck 能提前发现大部分引号和返回码问题。