🇯🇵 日本語 | 🇺🇸 English | 🇪🇸 Español | 🇵🇹 Português | 🇹🇭 ไทย | 🇨🇳 中文

【珍藏版】Bash 必学的 5 种模式与避错技巧

通过之前的 Bash 入门系列,您已经掌握了从基本命令到简单脚本编写的“黑窗”操作基础。想必您已经感受到,通过组合命令,日常工作变得轻松了一些。大家辛苦了!

好了,作为 Bash 篇的收官之作,这次我们将更进一步,从“能跑就行”的脚本,升级到“安全、易读、不易出错”的专业级脚本。我们将传授 5 个特别重要的模式,以及避免新手常犯“陷阱”的技巧。

接下来要介绍的并非新的高难度命令,而是关于“如何正确使用”已有知识的技巧,好比开车的诀窍。就像刚学会开车的人要学习在雨天和夜路安全行驶的技巧一样,通过今天的文章,您也将掌握在任何情况下都能安心执行的脚本编写方法!


模式 1:变量务必用“双引号”括起来!

这是 Bash 脚本中的绝对黄金法则。忘记用双引号 " " 包裹变量,是导致意外错误的最大原因。尤其当变量中包含空格时,问题会变得非常明显。

常见的错误:不加引号的变量

例如,我们来看下面这个试图创建包含空格的目录名的脚本。

#!/bin/bash
DIR_NAME="My Project"
mkdir $DIR_NAME

执行这个脚本后,Bash 会将命令解释为 mkdir My Project,结果会创建出 “My” 和 “Project” 这两个独立的目录。这并非我们期望的结果。


最佳实践:用 " " 包裹变量

要解决这个问题,只需将变量用双引号括起来即可。这样,Bash 就会正确地将包含空格的整个字符串识别为“一个整体”。

#!/bin/bash
DIR_NAME="My Project"
mkdir "$DIR_NAME" # 用双引号包裹变量!
echo "目录 '$DIR_NAME' 已创建。"

这个简单的习惯会让您的脚本变得更加健壮。请牢记:“变量总是用双引号括起来”


模式 2:出错时立即停止的安全设计

Bash 脚本有一个可怕之处:即使中途某个命令执行失败,它也会毫不在意地继续执行后续的命令。例如,一个“先移动到某个目录,再在其中删除文件”的脚本,如果移动失败了会怎样?很可能导致在错误的位置删除了文件,造成巨大灾难。

为防止这种情况,请在脚本开头写上这句“咒语”:

set -e

set -e 就像一个“安全装置”,一旦脚本中任何一个命令执行出错,它就会立即中止脚本的运行。让我们通过下面的脚本看看它的效果。


#!/bin/bash
set -e # 打开安全装置

echo "开始处理..."

# 尝试移动到一个不存在的目录,这里会发生错误
cd /non-existent-directory

# 因为有 set -e,这一行绝不会被执行
echo "这条消息不会显示。"

执行这个脚本时,处理流程会在 cd 命令失败的那一刻停止,最后的 echo 命令不会被执行。对于执行重要操作的脚本,请务必写上这一行。


模式 3:将命令的执行结果存入变量

在编写脚本时,我们经常会遇到需要“将一个命令的执行‘结果’用于另一个命令或变量”的场景。例如,想在备份文件名中加入当天的日期。

这时可以使用命令替换 (Command Substitution) 功能。写法是 $(命令)

#!/bin/bash
set -e

# 获取 YYYY-MM-DD 格式的今天日期,并存入变量
TODAY=$(date "+%Y-%m-%d")

# 将日期整合进文件名
BACKUP_FILENAME="backup_${TODAY}.tar.gz"

echo "备份文件名: $BACKUP_FILENAME"
# tar -czf "$BACKUP_FILENAME" /path/to/backup/source

$(date "+%Y-%m-%d") 这部分会被 date 命令的执行结果(例如:2025-07-06)所替换。这样就能轻松生成动态且易于理解的文件名。


模式 4:安全地逐行处理文件

读取文本文件(如域名列表、URL 列表等),并对每一行进行处理,是脚本的典型应用场景。但是,这个操作有一个新手容易掉入的“陷阱”。

常见的错误模式

for line in $(cat file.txt) 这样的写法,在文件名包含空格时无法正确处理,应当避免。

安全的最佳实践:`while read` 循环

安全且高效地逐行处理文件的标准模式是使用 while read 循环。它看起来可能有点复杂,但最好的方法是将其作为固定格式记住。

首先,我们准备一个待处理的列表文件 `domains.txt`。

example.com
example.net
example.org

接下来,是读取并处理这个文件的脚本。

#!/bin/bash
set -e

INPUT_FILE="domains.txt"

while IFS= read -r line
do
  echo "Processing domain: $line"
  # 在这里执行 ping $line 或 curl http://$line/ 等操作
done < "$INPUT_FILE"

这个语法可以保留行首和行尾的空格,并能正确处理特殊字符,因此可以应用于所有文本文件的处理。


模式 5:安全地创建和删除临时文件

在脚本处理过程中,有时需要创建临时的工作文件。这时,如果硬编码文件名,如 /tmp/my_temp_file,是很危险的。如果其他程序正在使用同名文件,或者脚本被同时多次执行,文件就可能被覆盖。

要安全地创建临时文件,请使用 mktemp 命令。它会创建一个独一无二、不会与任何文件重名的空文件。

#!/bin/bash
set -e

# 创建一个安全的临时文件,并将其名称存入变量
TEMP_FILE=$(mktemp)

# 确保在脚本退出时(无论是正常结束、出错还是被中断)总是删除该临时文件
trap 'rm -f "$TEMP_FILE"' EXIT

echo "已创建临时文件: $TEMP_FILE"
echo "正在向此文件写入数据..."
echo "some temporary data" > "$TEMP_FILE"

echo "文件内容:"
cat "$TEMP_FILE"

echo "处理完成。临时文件将被自动删除。"

此外,通过结合使用 trap 命令,您可以预设一个“清理”操作:“无论脚本因何种原因退出,最后都必须删除这个临时文件”。这可以防止服务器上残留不必要的垃圾文件。


总结

辛苦了!至此,Bash 入门系列就全部完结了。在最后一期中,我们学习了 5 个重要的模式,它们能让您的脚本从“玩具”升华为“专业工具”。

只要有意识地使用这些模式,您编写的脚本的可靠性就会大大增加,并且会变成易于维护的代码,方便未来的自己或他人阅读。请务必在今后的脚本编写中活用它们。衷心祝愿您的 Web 制作生涯,在获得了 Bash 这个强大工具后,变得更加富有创造性和效率!