PES
ZH English 한국어 日本語 中文 हिन्दी বাংলা اردو Español Português Français Deutsch Русский العربية Bahasa Indonesia Tiếng Việt ไทย Türkçe

如何开启通知

此浏览器或网址无法使用通知。请使用支持通知的浏览器,通过安全连接访问PES。

如果通知被屏蔽,请在浏览器设置中允许通知。

  1. 打开地址栏旁的站点设置或浏览器的站点设置,将此网站的通知设为允许。
  2. 在设备设置中允许浏览器发送通知,并检查勿扰模式或专注模式。
  3. 返回PES,刷新页面,然后通过铃铛开启通知。

在iPhone或iPad上,将PES添加到主屏幕,从主屏幕打开后允许通知。

我的学习进度
  1. 人工智能用法
  2. 终端命令
  3. 人工智能进阶
  4. Vibe 编程
  5. 人工智能证书 准备中
  6. 键盘
查看详情

学 Python 之前,先掌握 Shell 基础

学习 时,人们往往先想到 Python,但安装和运行 AI 工具所需的实用基础,是与 。

Shell 虽然不是构建 AI 的主要语言,却比 Python 更早出现,长期用于文件管理和日常任务自动化。

无需深入钻研,从几个常用命令开始,就能轻松入门,掌握受用一生的基本功。

一切工具背后的基础语言

Shell 编程真正驱动 AI 的语言

有助于运行程序、管理文件、自动化开发。 也能通过、应用、笔记本和 使用。是一种实用界面,不是每位 AI 用户的必要条件。

查看课程
  • 无需安装,立即练习
  • 兼容 macOS · Linux
  • 安全的
我的学习旅程 今天迈出第一步
已完成 0 / 12 课 0%
12阶段路线图
29个练习任务
0次命令运行
循序渐进

用 12 课掌握 Shell

从基础到 与开发工具安装,再到运行 Python、、 等其他语言,学完立即亲手运行。

入门 → 实战
  1. 第 01 课 已完成 下一课 初识终端 命令语法与当前位置 3 个任务 开始
  2. 第 02 课 已完成 下一课 文件与文件夹 创建、移动、删除和查看内容 3 个任务 开始
  3. 第 03 课 已完成 下一课 变量与展开 保存、复用和计算值 2 个任务 开始
  4. 第 04 课 已完成 下一课 条件与循环 用 if 判断,用 for 重复 2 个任务 开始
  5. 第 05 课 已完成 下一课 函数与脚本 创建自己的命令 1 个任务 开始
  6. 第 06 课 已完成 下一课 文本处理工具箱 grep 查找,sort·uniq·wc 统计 2 个任务 开始
  7. 第 07 课 已完成 下一课 管道与重定向 连接命令并把结果写入文件 2 个任务 开始
  8. 第 08 课 已完成 下一课 实用脚本 构建真正有用的自动化 1 个任务 开始
  9. 第 09 课 已完成 下一课 安全 Shell:引号与陷阱 养成防御式脚本习惯 2 个任务 开始
  10. 第 10 课 已完成 下一课 Node.js 命令 用 node、npm、npx 运行 JavaScript 3 个任务 开始
  11. 第 11 课 已完成 下一课 安装开发工具 把 Grok、Codex、Claude Code、Firebase 装进终端 3 个任务 开始
  12. 第 12 课 已完成 下一课 用 Shell 运行其他语言 直接在终端里驱动 Python、awk 和 sed 5 个任务 开始
为什么学 SHELL?

一次掌握,终身受用的计算机通用语言

亲手运行 AI 给出的答案

当你让 整理文件或自动化任务时,它通常会给出 。学会阅读 ,才能在运行前亲自确认是否安全。

随处可用的基础能力

Shell 是数十年来稳定而通用的计算机语言。学会一次,即可长期用于 macOS、Linux、、平台和 AI 工具。

macOS 用户也可以直接跟学

macOS 默认使用 ,但本课程中的和概念几乎都能原样运行。使用 可以明确通过 Bash 执行,除了下标起始编号这类极少数高级差异之外都能照搬。

实战示例

用一个 Shell 脚本搭建 Web 服务器

用大约 20 行 ,就能启动一个真正向返回页面的 Web 。这个例子生动地说明: 归根结底是"约定好互相收发一段文本"。

server.sh
#!/bin/bash

PORT=8084
PIPE=simple-web-server-pipe

rm -f "$PIPE"
mkfifo "$PIPE"

response() {
    read -r method path _
    echo "[$(date)] $method $path" >&2
    index=$(cat index.html)
    printf 'HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nConnection: close\r\n\r\n%s' \
      "$index"
}

while true; do
    response < "$PIPE" | nc -l "$PORT" > "$PIPE"
done
  1. mkfifo "$PIPE" 创建一个。 收到的请求和我们生成的响应都通过这条通道来回传递。
  2. nc -l "$PORT" 用 nc(netcat)打开 8084 ,等待浏览器连接。一行就代替了套接字服务器。
  3. response() 读取请求的第一行(方法与)并记录日志,把 index.html 作为 HTTP 200 响应返回。
  4. while true; do … done 响应后连接断开,重新开始以接待下一位访客,服务器因此持续运行。

把 index.html 放在同一目录,运行 bash server.sh,然后在浏览器中打开 localhost:8084。并非用于生产,但非常适合理解 HTTP 的原理。

第 01 课 · 动手实验

初识终端

学习输入、理解并找到。

4 个学习目标 3 个练习任务 约 10 分钟
立即练习
第 02 课 · 动手实验

文件与文件夹

练习创建、复制、移动、删除和读取文件与文件夹。

4 个学习目标 3 个练习任务 约 10 分钟
立即练习
第 03 课 · 动手实验

变量与展开

将值保存在中,并把变量、结果和计算结果嵌入文字。

4 个学习目标 2 个练习任务 约 10 分钟
立即练习
第 04 课 · 动手实验

条件与循环

使用 if 选择行为,使用 for 或 while 重复工作。

4 个学习目标 2 个练习任务 约 10 分钟
立即练习
第 05 课 · 动手实验

函数与脚本

把常用组合成,传递,并理解与 。

4 个学习目标 1 个练习任务 约 10 分钟
立即练习
第 06 课 · 动手实验

文本处理工具箱

查找匹配行、排序和去重文本,并统计行数或单词数。

4 个学习目标 2 个练习任务 约 10 分钟
立即练习
第 07 课 · 动手实验

管道与重定向

使用 | 连接输出与输入,使用 > 和 >> 把结果写入文件。

4 个学习目标 2 个练习任务 约 10 分钟
立即练习
第 08 课 · 动手实验

实用脚本

组合所学知识,编写能验证输入并安全自动化工作的。

4 个学习目标 1 个练习任务 约 10 分钟
立即练习
第 09 课 · 动手实验

安全 Shell:引号与陷阱

避免和陷阱,编写遇错安全停止的。

4 个学习目标 2 个练习任务 约 10 分钟
立即练习
第 10 课 · 动手实验

Node.js 命令

学习在使用 :查看版本、运行、用 管理包,以及用 一次性运行工具。

4 个学习目标 3 个练习任务 约 10 分钟
立即练习
第 11 课 · 动手实验

安装开发工具

简要说明如何在安装 编程助手与部署 。准备好 Node/ 后,多数工具只需一条即可开始。

4 个学习目标 3 个练习任务 约 10 分钟
立即练习
第 12 课 · 动手实验

用 Shell 运行其他语言

并不亲自做所有事,它是调度其他语言的指挥。学习用 -c 执行单行、用 传入多行程序,以及 最常用的两个工具: 与 。

6 个学习目标 5 个练习任务 约 10 分钟
立即练习
学习目标

本课你将做到

  1. 1

    使用“命令 [] [目标]”结构

  2. 2

    查看位置并切换文件夹

  3. 3

    使用 输出文字

  4. 4

    使用 man 和 --help 查找帮助

核心概念

掌握核心知识

01

终端与提示符

是用文字向计算机发出指令的窗口。$ 或 % 表示 已准备好;输入并按 Enter。

02

命令的三个部分

多数包含动作、和目标。例如 -l Documents 表示详细列出 Documents。

03

知道自己在哪里

查看, 切换目录, 查看内容。~ 表示,.. 表示上一级。

试一试

逐行运行

点击命令即可填入右侧终端。

注意

初学者常见错误

  • 和之间必须有空格:应写 -la。
  • ,应使用 ls 和 。
学习目标

本课你将做到

  1. 1

    创建文件夹和空文件

  2. 2

    复制、移动、重命名和删除

  3. 3

    使用 、、 查看内容

  4. 4

    安全使用删除

核心概念

掌握核心知识

01

创建 — mkdir 与 touch

创建文件夹, 创建空文件。mkdir -p 可以一次创建缺少的父目录。

02

复制、移动、重命名

保留原件并创建副本; 用于移动,也可通过 mv old new 重命名。

03

查看内容

显示全部内容, 和 显示开头或结尾。 不经过回收站,必须谨慎。

试一试

逐行运行

点击命令即可填入右侧终端。

注意

初学者常见错误

  • -rf 会无确认删除整个文件夹,请先检查。
  • 和 可能静默覆盖目标,建议使用 -i。
学习目标

本课你将做到

  1. 1

    创建并读取变量

  2. 2

    安全变量

  3. 3

    使用 $(( )) 计算

  4. 4

    使用 $( ) 获取命令结果

核心概念

掌握核心知识

01

创建和读取变量

使用 name=value 创建,使用 $name 读取。= 两边不能有空格。

02

用双引号保护值

使用 "$name" 可以保留值中的空格,这是安全 的核心习惯。

03

算术展开与命令替换

$(( 3 + 4 )) 得到 7;$() 把命令结果作为值。

试一试

逐行运行

点击命令即可填入右侧终端。

注意

初学者常见错误

  • = 周围的空格会让名称被当成。
  • 未的会按空格分割,默认使用 "$name"。
学习目标

本课你将做到

  1. 1

    使用 if / elif / else

  2. 2

    使用 [[ ]] 比较

  3. 3

    使用 for 处理列表

  4. 4

    区分数字和比较

核心概念

掌握核心知识

01

if 条件语句

if ; then ... fi 只在条件为真时执行。可加入 elif 和 else,并以 fi 结束。

02

使用 [[ ]] 比较

用 ==、!=,数字用 -gt/-lt/-eq,文件和文件夹用 -f、-d。

03

for 循环

for item in list; do ... done 会逐项处理列表,也可 {1..5} 或文件。

04

用 seq 重复固定次数

要重复固定次数(例如 1 到 20),可以用 生成数字并传给 for:for i in $(seq 1 20); do ... done,其中 $(seq 1 20) 会展开为 1 2 3 … 20。不要漏掉 in——写成 for i $(seq 1 20) 会报错,一定要保持「for in 列表」的顺序。同样的也可以用写成 for i in {1..20}。

试一试

逐行运行

点击命令即可填入右侧终端。

注意

初学者常见错误

  • [[ $x > 7 ]] 中的 > 比较文字,数字应使用 -gt。
  • [[ 和 ]] 内侧必须保留空格。
学习目标

本课你将做到

  1. 1

    定义并调用函数

  2. 2

    使用 $1 等参数

  3. 3

    说明 #!/bin/bash

  4. 4

    理解

核心概念

掌握核心知识

01

定义与调用函数

name() { ; } 为一组命令命名,内通过 $1、$2 读取。

02

脚本与 shebang

把保存在 .sh 文件中即可重复运行。 指定使用 。

03

权限与参数

先执行 +x hello.sh,再运行 ./hello.sh。使用 $1、$2、$@、$# 读取。

试一试

逐行运行

点击命令即可填入右侧终端。

注意

初学者常见错误

  • 未执行 +x 时可能出现 ,也可用 hello.sh。
  • 用 "$1" 以保留空格。
学习目标

本课你将做到

  1. 1

    使用 查找行

  2. 2

    使用 grep -i 和 -n

  3. 3

    使用 排序

  4. 4

    使用 统计

核心概念

掌握核心知识

01

grep — 查找

word file 只显示匹配行。-i 忽略,-n 显示行号,-r 递归搜索。

02

初识 sed 与 awk

用于查找替换; 把每行分成字段以处理表格数据。

03

rg (ripgrep) — 近年常用的查找工具

在里输入 的工具是 ripgrep。它和本单元的 一样按行查找,但默认会快速搜索整个文件夹,并跳过 .gitignore 中列出的文件。它的与 grep 并不完全相同,建议先掌握 grep 再搭配使用。这里的不支持 rg,请在自己的电脑上试用。

04

排序与统计

排序, 合并相邻重复行, -l 统计行数。

试一试

逐行运行

点击命令即可填入右侧终端。

注意

初学者常见错误

  • 不要把文件到自身,例如 ... file > file。
  • 无匹配时不输出;只需判断时使用 grep -q。
学习目标

本课你将做到

  1. 1

    使用 | 连接

  2. 2

    使用 > 保存输出

  3. 3

    使用 >> 追加

  4. 4

    理解流

核心概念

掌握核心知识

01

管道 ( | )

A | B 把 A 的输出直接交给 B。小工具可以组合成强大的一行流程。

02

重定向 ( >, >>, < )

> 覆盖,>> 追加,< 使用文件作为输入;2> 单独保存错误。

03

既显示又保存 — tee

在中间插入 ,就能把流经的内容原样送到屏幕(或下一条),同时也保存到文件。名字来自 T 形管道接头(tee)。> 会把输出「引流」到文件而在屏幕上消失,而 命令 | tee 文件 则一边显示一边保存。想追加而不覆盖就用 tee -a——在保留日志的同时还能亲眼看到结果,非常方便。

试一试

逐行运行

点击命令即可填入右侧终端。

注意

初学者常见错误

  • > 会立即覆盖目标;需要保留内容时用 >>。
  • 阶段可能在 中运行,修改不一定保留。
学习目标

本课你将做到

  1. 1

    通过 查看成功失败

  2. 2

    使用 && 与 || 连接处理

  3. 3

    使用 for 处理多个文件

  4. 4

    理解 定时执行

核心概念

掌握核心知识

01

退出码与 $?

成功返回0,失败返回其他值。 读取上次结果,A && B 只在 A 成功时运行 B。

02

自动化重复工作

把和文件组合起来,即可对许多目标自动执行相同工作。

03

定时执行 — cron

在固定时间运行。0 3 * * * 表示每天凌晨3点。

试一试

逐行运行

点击命令即可填入右侧终端。

注意

初学者常见错误

  • 关键失败时使用 command || exit 1 停止。
  • ,并在 中使用绝对路径。
学习目标

本课你将做到

  1. 1

    说明三种方式

  2. 2

    理解单词分割与通配

  3. 3

    使用 set -euo pipefail

  4. 4

    始终引用

核心概念

掌握核心知识

01

三种引用方式

"$var" 会展开但保留空格;'$var' 保持字面值;未的 $var 可能按空格分割并展开。

02

单词分割与通配

未的值会变成多个,* 或 ? 会展开成文件名,容易造成误操作。

03

防御式选项

set -euo pipefail 捕获错误、未定义和中间失败; 可提前发现问题。

试一试

逐行运行

点击命令即可填入右侧终端。

注意

初学者常见错误

  • 多数 事故源于遗漏,请养成始终引用的习惯。
  • 在 中使用 [[ $a = b && $c = d ]]。
学习目标

本课你将做到

  1. 1

    用 -v 查看 Node.js 版本

  2. 2

    用 node app.js 运行 文件

  3. 3

    用 npm 安装包并运行脚本

  4. 4

    用 npx 在不全局安装的情况下运行一次工具

核心概念

掌握核心知识

01

什么是 Node.js?

在之外(、)运行 。Web 应用、、构建和许多 编程助手都依赖它。学完 后掌握 Node,安装开发工具会轻松很多。

02

node 命令

用 -v(或 --version)查看版本。node app.js 运行文件;node -e "console.log(1+1)" 运行一行代码。

03

npm 与 package.json

负责安装与管理。 记录名称、版本、 与 dependencies。npm install 安装依赖;npm run start 运行脚本。 用于一次性运行。

试一试

逐行运行

点击命令即可填入右侧终端。

注意

初学者常见错误

  • 若 或 提示 not found,说明尚未安装 。请从 nodejs.org 或用 安装后重新打开。
  • npm install -g 容易造成权限与安全问题。优先使用 nvm,或在不用 sudo 的情况下配置全局。
学习目标

本课你将做到

  1. 1

    说明 是许多工具安装的前提

  2. 2

    了解 Claude Code、Codex、Grok、 的常见安装命令

  3. 3

    区分全局安装(-g)与一次性运行()

  4. 4

    养成安装后检查版本的习惯

核心概念

掌握核心知识

01

为什么要在终端安装工具?

现代开发不只靠编辑器。 编程助手(Grok Build、Codex、Claude Code)、 与包管理器都在运行。第10课的 Node/ 就是起点。

02

常见安装(简要)

官方方式可能变化,请以官方文档为准。Claude Code: -fsSL ://claude.ai/install.sh | (或 install -g @anthropic-/claude-code)。OpenAI Codex:curl -fsSL https://chatgpt.com/codex/install.sh | sh(或 npm install -g @openai/codex)。Grok:官方安装或 npm install -g @xai-official/grok。:npm install -g firebase-tools。安装后用 claude --version 等验证。

03

安全安装习惯

| 只使用可信官方。全局 权限出错时,优先修复 而不是 。团队与 CI 中用 devDependency 固定版本更安全。

试一试

逐行运行

点击命令即可填入右侧终端。

注意

初学者常见错误

  • 来源不明的 | 有风险。请先确认官方。
  • 名称相似但包名不同。请使用 @anthropic-/claude-code、@openai/codex、 等准确名称。
学习目标

本课你将做到

  1. 1

    能用 -c 和 -e 执行其他语言的单行代码

  2. 2

    能把程序保存为文件并用 python3 文件.py 运行

  3. 3

    能用 heredoc(<<PY)把多行程序交给

  4. 4

    能用 sed 批量修改文件中的文本

  5. 5

    能用 awk 从表格数据中取列并汇总

  6. 6

    能在运行 AI 给出的代码前先安全确认

核心概念

掌握核心知识

01

Shell 是指挥,不是独奏者

只用 完成所有计算很快就会碰壁。Shell 的角色是决定"何时叫谁":计算和数据交给 Python,表格汇总交给 ,文本批量修改交给 ,再由 Shell 把结果串起来。懂 Shell,就能调用自己从没学过的语言。

02

只传一行 — -c 与 -e

多数语言都有"把代码当作直接运行"的:Python 是 -c "代码", 是 -e "代码",Perl 是 perl -e,Ruby 是 ruby -e。只要养成用 python3 -c "print(2**10)" 代替计算器的习惯,就会强大得多。

03

保存为文件再运行

如果一段程序不是用一次就丢,就把它存成文件。把代码写进 hello.py,输入 hello.py 就能直接运行。再把第 5 课学过的 写在第一行 —— #!/usr/bin/env python3 —— 然后执行 +x hello.py 赋予,之后不用在前面加 python3,只写 ./hello.py 就能跑。运行结束后输入 就能看出是成功(0)还是失败(1),于是可以像第 8 课那样用 && 接上下一条。

04

传多行 — heredoc

程序有多行时,-c 就不方便了,这时就该用 。写 - <<'PY',从下一行起直到写着 PY 的那一行之前,都会作为整体交给 Python。中间的 - 表示"从标准输入而不是文件读取代码"。编程修改文件时经常使用的正是这种形式。

05

<<'PY' 与 <<PY 并不相同

用包住结束标记(<<'PY'),正文会原封不动地传过去;不包(<<PY), 会先替换正文里的 $ 和 $()。Python 代码里很少出现 $,但或中一旦有 $ 就会悄悄出错,所以传代码时以加引号为默认做法。

06

sed — 查找替换的流编辑器

's/查找/替换/' 只改每行第一处,末尾加 g(s/…/…/g)则改这一行的全部。在前面加行号或 // 可以挑选目标行(2s/…/…/、/error/s/…/…/),把 -n 和 p 配合使用则只输出选中的行。加上 -i 就不是改屏幕而是改文件本身。分隔符不必是 /,替换时写成 s|/old/path|/new/path| 会好读得多。要直接改文件本身,请用 sed -i.bak 's/查找/替换/' 文件:它把原文件保留为 文件.bak,而且在 macOS 和 Linux 上表现一致。只用 Linux(GNU sed)时可以省略备份名写成 sed -i,但 macOS 的 sed 要求 -i 后面必须跟名字,直接照写会报错(在 macOS 上不留备份地修改要写成 sed -i '' '…' 文件)。

07

awk — 处理表格的小型编程语言

不是,它本身就是一门语言。它按空白把每行切成 $1、$2、$3,NF 是列数,NR 是行号。基本形式是 awk '模式 { 动作 }':省略模式表示所有行,省略动作表示输出整行。开头放 BEGIN{}、结尾放 END{} 就能做准备与收尾,于是求和、平均、按项汇总都能一行搞定。

08

用管道把各种语言串起来

被写成从读、向标准输出写的程序之间,可以用自由连接。 sales.txt | '{print $2}' | -n | -3 就是"读文件 → 取第二列 → 按数值排序 → 只留最大的三个",一行完成。awk 与 就这样用管道相连,而 Python 则通过 -c 或 接收代码。这就是" 是指挥"的真正含义。

09

安全地运行 AI 给的代码

通常正是用这种 形式作答。粘贴之前只需确认三件事:①用眼睛读一遍它要改哪些文件;②看看有没有 或 > 这类覆盖操作;③重要文件先用 原文件 原文件.bak 备份。会读 ,就意味着能验证 AI 的答案。

试一试

逐行运行

点击命令即可填入右侧终端。

注意

初学者常见错误

  • 程序一定要用包起来。用双引号时 会把 $1 当成自己的替换成空:awk '{print $1}' 可以,awk "{print $1}" 则不行。
  • 的结束标记必须写在行首,前后不能有空格,且拼写完全一致。需要缩进时用 <<- 并以制表符缩进。
  • 传代码时以 <<'PY' 这样给标记加引号为默认做法。不加引号,代码里的 $ 会被替换成 Shell 变量而悄悄出错。
  • -i 会不可撤销地改写文件。先不加 -i 运行、在屏幕上确认结果,再加上它。
  • 在 macOS 上像 sed -i 's/…/…/' 文件 这样不写备份名,会报 undefined label 错误而文件原封不动 —— macOS 的 sed 要求 -i 后面跟名字。写成 sed -i.bak,同一条在 macOS 和 Linux 上都能通过。
  • sed 's/a/b/' file > file 会先清空文件再读取,内容因此丢失。请写到不同的文件名。
🚀 进阶学习 — 深入了解

读取用户输入

向用户询问一个值并存入。变量不必事先声明。

echo "你叫什么名字?"# 在屏幕上输出问题
read name# 把回答读入变量 name
echo "你好,$name!"# 使用读到的值

当前目录与子 Shell

除了 , $PWD 也能告诉你。用括号 ( ) 包起来的命令在单独的 中运行,所以在里面 不会改变外面的位置。

echo "我现在在 $PWD"# 通过使用当前
(cd /tmp; pwd)# 只在子 Shell 里移动 → 输出 /tmp
pwd# 外面仍在原来的位置

清屏与帮助

clear(或 Ctrl-L)用来清理屏幕。遇到不认识的,有三种帮助:内置命令用 help,手册用 man,详细文档用 info。

clear# 清空屏幕(与 Ctrl-L 相同)
help for# for 等内置命令的帮助
man ls# 的手册页(按 q 退出)

花括号展开

在 { } 中列出多个值或写一个范围, 就会一次生成许多名称。用一行建好整个文件夹树时尤其方便。

mkdir -p project/{src,tests,docs}# 一次创建三个文件夹
touch file{1..5}.txt# 创建 file1.txt 到 file5.txt 共五个文件
cp config.yaml{,.bak}# 备份技巧:config.yaml → config.yaml.bak

安全删除

删除后无法撤销。-i(逐个确认)和 -v(显示删除了什么)可以减少失误,trash- 则会把文件送进回收站。

rm -i old.txt# 删除前先询问是否真的要删
rm -v *.tmp# 显示删除了哪些文件
rm -r tempDir/# 删除文件夹及其中的全部内容(小心!)

更多 ls 选项

可以改变 的排序方式和列表格式。这三个值得学会。

ls -l# 每行一个,显示详细信息
ls -t# 最近修改的排在最前
ls -R# 连所有子文件夹也一起列出(递归)

参数展开

在 ${ } 里取出值的同时,还能截取或替换其中的一部分。这是加工值最强大的工具。

echo "${var/Some/A}"# 把第一个 Some 替换成 A
echo "${var//Some/A}"# // 会把所有 Some 都替换成 A
echo "${var:0:7}"# 从第 0 个字符起只取 7 个(子)
echo "${#var}"# 字符串的长度

默认值与大小写

为空时可以给一个默认值,也可以一次性转换。

echo "${foo:-默认值}"# foo 为空时改用“默认值”
: "${NAME:=访客}"# NAME 不存在时设为“访客”并保留
echo "${var^^}"# 全部大写( 4+)
echo "${var,,}"# 全部小写

截取路径

# 从前面截,% 从后面截。写两次(##、%%)就尽量多截——从中只取出文件名或文件夹就靠它。

path="/usr/local/bin/run.sh"# 示例路径
echo "${path##*/}"# 删到最后一个 / 为止 → run.sh()
echo "${path%/*}"# 删掉最后一个 / 及其后面 → /usr/local/bin(dirname)
echo "${path%.sh}"# 只删掉 .sh 扩展名

数组

把几个值放进括号里就成了:用 [编号] 取出一个,用 [@] 取出全部,${#array[@]} 给出个数。

array=(苹果 香蕉 葡萄)# 创建一个有三个元素的数组
echo "${array[0]}"# 第一个 → 苹果(编号从 0 开始)
echo "${array[@]}"# 全部 → 苹果 香蕉 葡萄
echo "${#array[@]}"# 个数 → 3

关联数组

用 -A 创建的保存“名字 → 值”的配对(相当于其他语言中的字典或映射)。

declare -A person# 声明一个关联数组
person[name]="爱丽丝"# 把值存到标签 name 下
echo "${person[name]}"# 取出 → 爱丽丝
for k in "${!person[@]}"; do echo "$k"; done# 遍历所有键

内置变量与算术

会替你填好一些。写在 $(( )) 里,乘方和余数也能算。要算小数就用 。

echo "$?"# 上一条的(0 = 成功)
echo "$RANDOM"# 0 到 32767 之间的随机数
echo "$(( 2 ** 10 ))"# 乘方 → 1024
echo "scale=2; 10/3" | bc# 小数运算 → 3.33

使用 printf 格式化

在不同系统上的表现略有差异。 在哪里都一样,还能精确控制宽度、对齐和小数位数。

printf "你好,%s!\n" "世界"# 把值填到 %s 的位置 → 你好,世界!
printf "%.2f\n" 3.14159# 保留两位小数 → 3.14
printf "%05d\n" 42# 不足五位用 0 补齐 → 00042

使用 case 分支

把一个值和许多模式比较时,case 比一串 if 更整洁(相当于其他语言中的 switch)。

case "$x" in# 根据 x 的值
0) echo "零";;# 值为 0 时
1) echo "一";;# 值为 1 时
*) echo "其他";; esac# * 匹配其余所有情况

for、while 与 until

for 遍历列表或范围,while 在条件为真时一直,until 在条件为假时一直循环。另外还有 C 风格的 for。

for ((i=1; i<=3; i++)); do echo "$i"; done# C 风格的 for
while (( count < 3 )); do ((count++)); done# 条件为真时一直重复
until (( count >= 3 )); do ((count++)); done# 条件为假时一直重复

正则匹配与文件检查

=~ 检查是否符合模式。-e、-f、-d 等用来检查文件或文件夹是否存在,以及它是哪一种。

if [[ "$email" =~ ^[a-z]+@[a-z]+\. ]]; then echo 匹配; fi# 正则表达式匹配
if [[ -f "$file" ]]; then echo "文件存在"; fi# -f:是普通文件吗?
if [[ -d "$dir" ]]; then echo "文件夹存在"; fi# -d:是文件夹吗?
if [[ -z "$name" ]]; then echo "为空"; fi# -z:是空的吗?

变量作用域

local 创建只在内部使用的, 创建不能修改的常量。declare 可以设置整数(-i)、小写(-l)、大写(-u)等属性。

greet() { local msg="你好"; echo "$msg $1"; }# msg 在函数外看不到
readonly PI=3.14# 不能修改的常量
declare -i num=42; num+=10# 整数类型 → 自动完成运算(52)
declare -u up="hi"; echo "$up"# 总是大写 → HI

使用 getopts 处理选项

让接受 -v 或 -f 文件名 这类的标准工具。字母后面的冒号(:)表示“这个选项需要一个值”。

while getopts ":vf:" opt; do# v 不需要值,f 需要一个值
case $opt in# 按选项
v) verbose=true ;;# 有 -v 时打开 verbose
f) file="$OPTARG" ;; esac; done# -f 的值在 中

source 与 export

source(或 .)在当前 中运行另一个文件,载入其中的和设置。export 则把也传给。

source ./lib/helpers.sh# 把另一个文件的函数和变量载入当前 Shell
. ~/.bashrc# . 是 source 的简写
export API_KEY="abc123"# 让子进程也能看到它

更多 grep 选项

加上, 会强大得多。可以组合递归搜索、行号、排除和计数。

grep -r "TODO" ./src# -r:递归搜索整个文件夹
grep -n "error" app.log# -n:带上行号
grep -v "debug" app.log# -v:只显示不含该词的行(反向)
grep -c "error" app.log# -c:只显示匹配的行数

使用 sed 编辑流

在文本流过时进行编辑。它能替换、删除和选取范围,-i 会直接修改文件本身(请保留备份)。

sed 's/okay/great/g' file.txt# 把所有 okay 换成 great
sed '/^#/d' file.txt# 删除以 # 开头的注释行
sed -i.bak 's/old/new/g' file.txt# 直接修改文件 + 留下 .bak 备份
sed -n '/error/p' log.txt# 只输出含有 error 的行

使用 awk 处理列

按空格(或 -F 指定的字符)把每行切开,把各段当作列 $1、$2 … 来处理。它擅长求和、筛选和统计。

echo 'a b c' | awk '{print $2}'# 第二列 → b
awk -F',' '{print $3}' data.csv# 按逗号切分,取第三列
awk -F',' '$2 > 25' people.csv# 第二列大于 25 的行
awk '{s+=$1} END{print s}' nums.txt# 第一列的合计

cut、sort、uniq 与 xargs

用把小工具连起来,就能做强大的数据处理。 把一条的输出变成下一条命令的。

cut -d ',' -f 1 file.csv# 只取按逗号分隔的第一列
sort file.txt | uniq -c# 先排序,再统计重复次数
find . -name "*.tmp" | xargs rm -f# 把找到的文件交给 删除
find . -name "*.txt" -print0 | xargs -0 rm# 文件名带空格也安全(-0)

Here document 与 here string

<< EOF()把多行文字整体交给作为输入。<<<()则是送入一行短文字的轻便方法。

cat << EOF# 到 EOF 为止的几行成为输入
多行 文字 EOF# 两个 EOF 之间的内容就是正文
grep "香蕉" <<< "苹果 香蕉 葡萄"# 用 <<< 输入一行

标准错误与 /dev/null

(stdout)和标准错误(stderr)走的是不同的通道。2> 只接收错误,2>&1 把错误送到和输出相同的地方,/dev/null 是专门丢弃东西的地方。

command 2> error.log# 只把错误信息写入文件
command > out.log 2>&1# 输出和错误一起写入 out.log
command > /dev/null 2>&1# 输出和错误都丢掉(静默)

进程替换

<() 把一条命令的输出当作文件一样传出去。不用临时文件就能直接比较两条命令的结果,非常方便。

diff <(ls dir1) <(ls dir2)# 直接比较两个文件夹的列表
while read l; do echo "$l"; done < <(ls)# 里设置的在循环结束后仍然保留

命令替换

$() 把命令的结果像值一样嵌进句子里。比起反(`),更推荐 $( )——它可以嵌套。

echo "这里有 $(ls | wc -l) 个文件"# 把文件个数嵌进句子
today=$(date +%Y-%m-%d)# 把今天的日期存入

使用 trap 清理

trap 设定收到(退出、错误、中断)时要运行的。用来清理临时文件尤其方便。

TMP=$(mktemp)# 安全地创建临时文件
cleanup() { rm -f "$TMP"; }# 清理用的
trap cleanup EXIT# 脚本结束时总会清理
trap 'echo 已中断; exit 1' SIGINT# 按下 Ctrl-C 也能安全处理

防御式 set 选项

在开头写上 set ,脚本就更不怕出错。-e(出错即停)、-u(禁止使用未设置的)和 -o pipefail(察觉中的失败)一起使用。-x 用于。

set -euo pipefail# 稳健脚本的标准第一行
set -x# 逐条输出正在运行的(调试)
set +x# 关闭调试

后台任务与 wait

在后面加上 &,它就作为运行。jobs 列出这些任务,wait 等到它们全部结束。

sleep 5 &# 在后台运行
jobs# 仍在运行的后台任务列表
wait# 等到所有后台任务都结束
time sleep 1# 测量命令用了多长时间

常用安全模式

真实中反复出现的防御模式:检查必需的值、检查是否存在、失败时立即停止。

: "${VAR:?必须设置 VAR}"# 缺少 VAR 时报错并停止
command -v jq && echo "已找到 jq"# 检查命令是否已安装
cp a b || { echo 失败; exit 1; }# 失败时输出提示并停止

理解每个 set 选项

set -euo pipefail 是三个的组合。知道每一个能防止什么事故,就明白它为什么成了标准写法。

set -e# 只要有失败就立即停止
set -u# 使用未定义的会报错(能发现拼写错误)
set -o pipefail# 中间一步失败,整个管道就算失败

使用 shopt 调整通配

调整文件名的匹配方式()。globstar 让 ** 深入子文件夹,nullglob 在没有匹配时给出空值。

shopt -s globstar# ** 也能匹配到子文件夹里( 4+)
for f in **/*.sh; do echo "$f"; done# 所有子文件夹中的每个 .sh 文件
shopt -s nullglob# 没有匹配时给出空值,而不是模式原文

IFS 与安全逐行读取

(内部字段分隔符)决定单词分割时在哪里切开。要安全地逐行读取文件,就把 IFS= 和 read -r 一起用。

IFS=',' read -ra f <<< "a,b,c"# 按逗号切分,存入 f
while IFS= read -r line; do# 保留空格和特殊字符
echo "$line"; done < file.txt# 安全地一次读取一行

用 nvm 管理版本

不同的项目可能需要不同版本的 Node。 可以安装多个版本并在它们之间切换。

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash# 安装 nvm(版本号请查看官方文档)
nvm install 22# 安装 Node 22
nvm use 22# 在当前 中使用 Node 22
node -v# 确认切换后的版本

npm scripts 与本地二进制

中的 运行时会把 _modules/.bin 加进 ,所以不用全局安装也能使用项目里的工具。

npm init -y# 快速生成 package.json
npm install lodash# 添加运行时依赖
npm install -D typescript# 只在开发时使用的依赖
npm run build# 运行 scripts.build

用 npx 一次性运行

想不全局安装、只运行一次最新版本的工具时,用 。对版本经常变化的 尤其有用。

npx create-next-app@latest my-app# 搭建项目骨架的示例
npx prettier --write .# 运行 prettier(本地的或下载的)
npx --yes cowsay hello# 不询问确认,直接运行一次

AI 编程助手安装备忘

用官方安装或全局 包来安装。装好后立刻用版本检查。

curl -fsSL https://claude.ai/install.sh | bash# Claude Code(Anthropic)
curl -fsSL https://chatgpt.com/codex/install.sh | sh# OpenAI Codex
npm install -g @xai-official/grok# Grok CLI(以 npm 方式安装为例)
claude --version && codex --version# 检查安装(示例)

Firebase 与其他必备 CLI

用于部署、登录和托管的 ,常和快速的包管理器 pnpm 一起安装。

npm install -g firebase-tools# Firebase CLI
firebase login# 通过登录
firebase projects:list# 项目列表
npm install -g pnpm# 全局安装 pnpm

PATH 与权限问题

如果安装成功却找不到,那就是 的问题。用 which 查看位置,并检查 的 设置。

which node npm# 程序所在的位置
echo "$PATH"# 查看搜索
npm config get prefix# 全局安装的位置
command -v firebase || echo "not found"# 检查是否已安装

各语言的单行执行选项

几乎每种语言都有一个“把代码作为、立即运行”的。只是选项字母不同,用法完全一样。

python3 -c "import sys; print(sys.version)"# Python 单行
node -e "console.log(1 + 1)"# 单行
perl -e 'print "hello\n"'# Perl 单行
ruby -e 'puts (1..5).to_a'# Ruby 单行
php -r 'echo PHP_VERSION;'# PHP 用 -r

AI 修改文件时使用的模式

让 修改代码时,得到的答案几乎总是这种形式:用 传入一小段 Python 程序,读取文件、替换、再写回去。关键是先用 assert 确认要替换的内容确实存在。

python3 - <<'PY'# 从这里到 PY 是一段 Python 程序
p = "src/app.py"# 要修改的文件
s = open(p, encoding="utf-8").read()# 读取整个文件
old = "before text"# 要查找的字符串(少了这一行会出现 NameError)
new = "after text"# 要换上的字符串
assert old in s# 找不到目标就在这里停下(最重要的一行)
s = s.replace(old, new)# 替换
open(p, "w", encoding="utf-8").write(s)# 写回文件
PY# heredoc 结束——必须顶格写在行首

heredoc 应用 — 生成配置文件

在中生成多行的配置或文档时, 也是最整洁的办法。标记不加时,$ 会当场被替换成值。

cat <<EOF > .env# 标记不加引号 → 变量会被替换
PORT=$PORT# $PORT 以实际的值保存
EOF# 到这里结束
cat <<'EOF' > template.txt# 加了引号 → $PORT 保持原样
bash <<< "echo one-liner"# 用 只传一行

sed 进阶 — 精确定位要改的行

在前面加上地址(行号或),就只改那些行。用 -i 直接修改文件时,加上 -i.bak 这样的扩展名——既能留下备份,在 macOS 和 Linux 上表现也一样。

sed -n '10,20p' log.txt# 只输出第 10 到 20 行
sed '/^#/d' config.txt# 删除以 # 开头的注释行
sed -i.bak 's/3000/8080/' config.txt# 修改文件,同时留下备份(.bak)
sed -E 's/([a-z]+)@([a-z.]+)/\2 \/ \1/' mail.txt# 用分组调换顺序
sed 's/error/ERROR/gI' log.txt# 忽略,全部替换
printf 'appended\n' >> notes.txt# 追加到最后一行之后(在哪里都能用)

awk 进阶 — 汇总与格式化

的真正实力体现在汇总和 格式化上。读取表格、按项目分组、整齐输出,一行就能完成。

awk '{sum[$1] += $2} END {for (k in sum) printf "%-10s %5d\n", k, sum[k]}' sales.txt# 按项目求合计,以表格输出
awk -F, '{print $2}' data.csv# 处理 时,-F, 按逗号切分
awk 'NF > 0' notes.txt# 去掉空行(只写模式就会输出该行)
awk '{n = split($0, a, "/"); print a[n]}' paths.txt# 从中只取文件名
awk 'NR == FNR {m[$1] = $2; next} $1 in m {print $1, m[$1], $2}' a.txt b.txt# 连接两个文件(join)
awk 'BEGIN {printf "%.2f\n", 22 / 7}'# 只写 BEGIN 就成了计算器

jq 与 xargs — 连接各种语言的胶水

用 处理,“对找到的每个结果运行”用 。两个都会用,能用连起来的范围就大大扩展了。

curl -s https://api.example.com/u | jq '.name'# 从 JSON 中取一个字段
jq -r '.items[] | .id' data.json# 把展开成每行一项(-r 去掉)
ls *.txt | xargs wc -l# 对找到的每个文件运行命令
grep -rlZ TODO . | xargs -0 sed -i.bak 's/TODO/DONE/g'# 用 + 批量修改(-Z 和 -0 让带空格的文件名也安全,并保留备份)

参考 Learn X in Y Minutes(Bash,CC BY-SA)重新编写。部分命令仅供参考。

课程完成!太棒了,你又前进了一步。

学习指南

人工智能

人工智能资格证

学习

Vibe 编程

游戏开发

练习

导师

聊天

论坛

创作

社区

更多

术语词典

选一个你不认识的词吧,可以看到简单的解释和相关术语。

还没有匹配的术语。

选择一个术语即可查看解释。