必备 Shell 脚本基础,你应先了解
Source: Dev.to
介绍
我之前写过一篇关于 Shell 脚本的文章,令我惊讶的是,它的阅读量远超预期。
由于 Shell 脚本并不是一种“潮流”技术,我原本以为不会有太大兴趣。
这次经历让我意识到:
想学习 Shell 脚本的人可能比我们想象的要多。
因此在本文中,我想分享一份 Shell 脚本基础要点的精要。
本指南旨在覆盖 编写第一段 Shell 脚本时避免卡住的最低必备知识。我不打算深入每个主题,而是侧重广度和实用认知。
如果你符合以下情况,本篇文章尤其适用:
- ✅ 从未编写过 Shell 脚本
- ✅ 曾尝试过一次但遇到困难
- ✅ 想了解 Shell 脚本与其他语言的区别
Shell 脚本的基本规则
.sh 扩展名是一种约定
从技术上讲,Shell 脚本可以使用任何文件扩展名,但 .sh 是被广泛接受的约定。
hello.sh
backup.sh
deploy.sh
使用 .sh 可以在编辑器和 GitHub 上获得语法高亮,所以除非有特别的原因不使用,否则请坚持使用它。
在第一行写 Shebang (#!)
Shell 脚本应以 shebang 开头:
#!/bin/bash
Shebang 指定 哪个 Shell 应该执行该脚本。它以 #! 开头,后面跟着 Shell 的完整路径。
每行一条命令
在 Shell 脚本中,换行符用于分隔命令,因此基本规则是 每行一条命令。
如果想把一条命令拆成多行,使用 \:
echo "This is \
one command"
注释使用 #
注释以 # 开头。也可以在行中间放置注释。没有原生方式一次性注释多行。
# This is a comment
echo "hello" # inline comments are allowed
Source: …
处理变量
定义变量
变量可以直接使用以下方式自动创建:
variable_name=value
无需声明。
变量命名规则
- 允许的字符:字母、数字和
_ - 不能以数字开头
- 通常使用小写蛇形命名(snake_case)
- 变量默认被视为字符串
如果需要整数变量,需要显式声明:
# 字符串变量
sum=2+9
echo $sum # → 2+9
# 整数变量
declare -i sum
sum=2+9
echo $sum # → 11
引用变量
要引用变量,需要在前面加 $:
name="Alice"
echo $name # → Alice
在 Bash 中,引用未定义的变量不会导致错误——它会展开为空字符串:
echo $undefined # → (empty output)
为了清晰地区分变量名和周围的文本,可以使用 {}:
item="pen"
echo "I have many ${item}s" # → I have many pens
单引号 vs. 双引号
引号的行为取决于其类型:
| 引号 | 行为 |
|---|---|
" | 变量会被展开 |
' | 变量不会被展开 |
name="Alice"
echo "$name" # → Alice
echo '$name' # → $name
在双引号内部转义字符时,使用 \:
echo "\$name" # → $name
常用控制结构
条件分支(if / case)
if 语句
if [ condition ]; then
do_something
elif [ another_condition ]; then
do_something_else
else
fallback
fi
有两种条件写法([] 和 [[]])。如果你想了解它们的区别,请参阅这篇文章:
Shell 脚本中 [ 与 [[ 的区别是什么?
case 语句
case 在处理多个模式时非常有用:
case "$var" in
start)
echo "start"
;;
stop)
echo "stop"
;;
*)
echo "other"
;;
esac
循环(for / while)
for 循环
for value in a b c; do
echo $value
done
while 循环
declare -i count=0
while [ $count -lt 5 ]; do
echo $count
count=$count+1
done
可以这样写一个无限循环:
while true; do
echo "looping..."
sleep 1
done
函数
函数定义如下:
hello() {
echo "Hello $1 and $2"
}
参数可以通过 $1、$2、$3 等访问。
调用函数:
hello "Alice" "Bob" # → Hello Alice and Bob
Shell‑Specific Concepts
退出状态
在 Linux 上,每个命令都会返回一个 退出状态:
- 0 → 成功
- 非 0 → 失败
退出状态不会自动显示。你可以使用 $? 来查看它:
ls /usr
# → bin libexec sbin standalone X11R6 lib local share X11
echo $? # → 0
ls /aaa
# → ls: /aaa: No such file or directory
echo $? # → 1
在 if 语句中使用退出状态时,值为 0 被视为 真(即命令成功),而非 0 的值被视为 假。
语句
- 0 被视为 true
- 非零 被视为 false
if ls /usr; then
echo "success"
else
echo "failure"
fi
# → success
if ls /aaa; then
echo "success"
else
echo "failure"
fi
# → failure
命令替换
您可以使用 $(…) 将命令输出存储到变量中:
now=$(date)
echo $now
# → Fri Dec 12 19:47:14 JST 2025
路径名展开(Globbing)
Shell 可以将 *、? 等模式展开为多个文件名。
示例
ls
# → file1.txt file2.txt string.c string.h string.txt
# ? matches a single character
ls string.?
# → string.c string.h
# * matches any string
ls *.txt
# → file1.txt file2.txt string.txt
# [] matches one of the listed characters
ls string.[ch]
# → string.c string.h
手动运行 Shell 脚本
方法 1:直接执行(推荐)
./hello.sh
- 指定脚本路径(相对或绝对)。
- 使用 shebang 定义的 shell 执行。
- 需要执行权限:
chmod +x hello.sh。
✅ ./hello.sh
❌ hello.sh # script name alone is not enough
方法 2:传递给 Shell
bash hello.sh
- 不需要执行权限。
- 必须手动选择正确的 shell。
结论
本文概述了 在编写你的第一个 shell 脚本时避免卡住所需的最低知识。
还有许多更重要的模式和技巧需要学习,所以我计划撰写后续文章,深入探讨具体主题。
💬 你呢?
- 在你第一次学习 shell 脚本时,最让人困惑的部分是什么?
- 有没有哪些 shell 脚本的规则或行为让你感到惊讶?
- 你想看到关于某个特定主题的更深入文章吗(例如
if条件、引用或调试)?