脚本是什么
Shell 就是把命令一条条执行。命令多了、还要按条件重复执行时,手动输入就很麻烦,于是把它们写进一个文本文件,这就是脚本。
最小的脚本通常有 Shebang、命令和注释:
#!/usr/bin/env bash
# 输出一行文字
echo "hello world"
保存为 test.sh 后,可以直接交给 Bash 执行:
bash test.sh
也可以加执行权限后直接运行:
chmod +x test.sh
./test.sh
#!/usr/bin/env bash 会从 PATH 中找到 Bash,比把路径写死成 /bin/bash 更灵活。脚本名是否使用 .sh 后缀不影响执行。
最小的变量用法
变量赋值时等号两边不能有空格,读取时加 $。路径和文本通常要加双引号:
name="小明"
echo "你好,$name"
脚本参数也可以直接读取:
echo "脚本名:$0"
echo "第一个参数:$1"
echo "参数数量:$#"
for item in "$@"; do
echo "参数:$item"
done
$@ 要放在双引号里,才能保留参数中原有的空格。参数超过 9 个时,用 ${10} 这样的形式读取。需要逐个吃掉参数时,可以配合 shift:
while [ "$#" -gt 0 ]; do
echo "当前参数:$1"
shift
done
选项较多时,用 getopts 解析会比手写判断清楚:
while getopts "n:f:" opt; do
case "$opt" in
n) name="$OPTARG" ;;
f) file="$OPTARG" ;;
*) exit 2 ;;
esac
done
shift "$((OPTIND - 1))"
条件判断
if 判断的其实是命令退出状态:返回 0 表示成功,其他值表示失败。
if [ -f "$1" ]; then
echo "这是一个普通文件"
elif [ -d "$1" ]; then
echo "这是一个目录"
else
echo "路径不存在"
fi
[ 是 test 的另一种写法,括号和表达式之间必须有空格。Bash 专用的 [[ ... ]] 更宽松,还支持正则:
if [[ "$name" =~ ^[[:alpha:]]+$ ]]; then
echo "看起来像一个英文名字"
fi
多值判断可以用 case:
case "$1" in
start) echo "启动" ;;
stop) echo "停止" ;;
*) echo "用法:$0 {start|stop}" >&2; exit 2 ;;
esac
循环
for 适合遍历参数或列表,while 适合满足条件时反复执行,until 则是条件成功前反复执行:
for file in "$@"; do
echo "$file"
done
count=0
while [ "$count" -lt 3 ]; do
echo "$count"
count=$((count + 1))
done
循环中可以用 break 提前结束,用 continue 跳过本轮。文件名遍历时要注意没有匹配项的情况;需要递归匹配时再考虑 globstar,不要把 glob 当成正则表达式。
退出码
每条命令都有退出码,$? 只能读取紧挨着的上一条命令:
cp "$source" "$target"
if [ "$?" -ne 0 ]; then
echo "复制失败" >&2
exit 1
fi
更常见的写法是直接把命令放进 if。脚本结束时可以用 exit 0 表示成功,用非零值表示失败。
if ! [ -r "$1" ]; then
echo "文件不可读:$1" >&2
exit 1
fi
&& 表示前一条成功后才执行,|| 表示前一条失败后才执行:
mkdir -p build && cd build || exit 1
直接执行脚本会在子 Shell 中运行;想让脚本修改当前 Shell 的变量或目录,需要使用 source script.sh(或 . script.sh)。调试时可以临时使用 bash -x script.sh 查看每条实际执行的命令。
DISCUSSION
评论 0
还没有评论,来留下第一条吧。