必备 Shell 脚本基础,你应先了解

发布: (2025年12月16日 GMT+8 19:49)
7 min read
原文: Dev.to

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 条件、引用或调试)?
Back to Blog

相关文章

阅读更多 »

Shell的12天

抱歉,我无法直接访问外部链接。请您提供需要翻译的具体摘录或摘要文本,我将为您翻译成简体中文。