亲手运行 AI 给出的答案
当你让 整理文件或自动化任务时,它通常会给出 。学会阅读 ,才能在运行前亲自确认是否安全。
学习 时,人们往往先想到 Python,但安装和运行 AI 工具所需的实用基础,是与 。
Shell 虽然不是构建 AI 的主要语言,却比 Python 更早出现,长期用于文件管理和日常任务自动化。
无需深入钻研,从几个常用命令开始,就能轻松入门,掌握受用一生的基本功。
有助于运行程序、管理文件、自动化开发。 也能通过、应用、笔记本和 使用。是一种实用界面,不是每位 AI 用户的必要条件。
从基础到 与开发工具安装,再到运行 Python、、 等其他语言,学完立即亲手运行。
当你让 整理文件或自动化任务时,它通常会给出 。学会阅读 ,才能在运行前亲自确认是否安全。
Shell 是数十年来稳定而通用的计算机语言。学会一次,即可长期用于 macOS、Linux、、平台和 AI 工具。
macOS 默认使用 ,但本课程中的和概念几乎都能原样运行。使用 可以明确通过 Bash 执行,除了下标起始编号这类极少数高级差异之外都能照搬。
用大约 20 行 ,就能启动一个真正向返回页面的 Web 。这个例子生动地说明: 归根结底是"约定好互相收发一段文本"。
#!/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
mkfifo "$PIPE"
创建一个。 收到的请求和我们生成的响应都通过这条通道来回传递。
nc -l "$PORT"
用 nc(netcat)打开 8084 ,等待浏览器连接。一行就代替了套接字服务器。
response()
读取请求的第一行(方法与)并记录日志,把 index.html 作为 HTTP 200 响应返回。
while true; do … done
响应后连接断开,重新开始以接待下一位访客,服务器因此持续运行。
把 index.html 放在同一目录,运行 bash server.sh,然后在浏览器中打开 localhost:8084。并非用于生产,但非常适合理解 HTTP 的原理。
学习输入、理解并找到。
练习创建、复制、移动、删除和读取文件与文件夹。
将值保存在中,并把变量、结果和计算结果嵌入文字。
使用 if 选择行为,使用 for 或 while 重复工作。
把常用组合成,传递,并理解与 。
查找匹配行、排序和去重文本,并统计行数或单词数。
使用 | 连接输出与输入,使用 > 和 >> 把结果写入文件。
组合所学知识,编写能验证输入并安全自动化工作的。
避免和陷阱,编写遇错安全停止的。
学习在使用 :查看版本、运行、用 管理包,以及用 一次性运行工具。
简要说明如何在安装 编程助手与部署 。准备好 Node/ 后,多数工具只需一条即可开始。
并不亲自做所有事,它是调度其他语言的指挥。学习用 -c 执行单行、用 传入多行程序,以及 最常用的两个工具: 与 。
使用“命令 [] [目标]”结构
查看位置并切换文件夹
使用 输出文字
使用 man 和 --help 查找帮助
是用文字向计算机发出指令的窗口。$ 或 % 表示 已准备好;输入并按 Enter。
多数包含动作、和目标。例如 -l Documents 表示详细列出 Documents。
查看, 切换目录, 查看内容。~ 表示,.. 表示上一级。
点击命令即可填入右侧终端。
创建文件夹和空文件
复制、移动、重命名和删除
使用 、、 查看内容
安全使用删除
创建文件夹, 创建空文件。mkdir -p 可以一次创建缺少的父目录。
保留原件并创建副本; 用于移动,也可通过 mv old new 重命名。
显示全部内容, 和 显示开头或结尾。 不经过回收站,必须谨慎。
点击命令即可填入右侧终端。
创建并读取变量
安全变量
使用 $(( )) 计算
使用 $( ) 获取命令结果
使用 name=value 创建,使用 $name 读取。= 两边不能有空格。
使用 "$name" 可以保留值中的空格,这是安全 的核心习惯。
$(( 3 + 4 )) 得到 7;$() 把命令结果作为值。
点击命令即可填入右侧终端。
使用 if / elif / else
使用 [[ ]] 比较
使用 for 处理列表
区分数字和比较
if ; then ... fi 只在条件为真时执行。可加入 elif 和 else,并以 fi 结束。
用 ==、!=,数字用 -gt/-lt/-eq,文件和文件夹用 -f、-d。
for item in list; do ... done 会逐项处理列表,也可 {1..5} 或文件。
要重复固定次数(例如 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}。
点击命令即可填入右侧终端。
定义并调用函数
使用 $1 等参数
说明 #!/bin/bash
理解
name() { ; } 为一组命令命名,内通过 $1、$2 读取。
把保存在 .sh 文件中即可重复运行。 指定使用 。
先执行 +x hello.sh,再运行 ./hello.sh。使用 $1、$2、$@、$# 读取。
点击命令即可填入右侧终端。
使用 查找行
使用 grep -i 和 -n
使用 排序
使用 统计
word file 只显示匹配行。-i 忽略,-n 显示行号,-r 递归搜索。
用于查找替换; 把每行分成字段以处理表格数据。
在里输入 的工具是 ripgrep。它和本单元的 一样按行查找,但默认会快速搜索整个文件夹,并跳过 .gitignore 中列出的文件。它的与 grep 并不完全相同,建议先掌握 grep 再搭配使用。这里的不支持 rg,请在自己的电脑上试用。
排序, 合并相邻重复行, -l 统计行数。
点击命令即可填入右侧终端。
使用 | 连接
使用 > 保存输出
使用 >> 追加
理解流
A | B 把 A 的输出直接交给 B。小工具可以组合成强大的一行流程。
> 覆盖,>> 追加,< 使用文件作为输入;2> 单独保存错误。
在中间插入 ,就能把流经的内容原样送到屏幕(或下一条),同时也保存到文件。名字来自 T 形管道接头(tee)。> 会把输出「引流」到文件而在屏幕上消失,而 命令 | tee 文件 则一边显示一边保存。想追加而不覆盖就用 tee -a——在保留日志的同时还能亲眼看到结果,非常方便。
点击命令即可填入右侧终端。
通过 查看成功失败
使用 && 与 || 连接处理
使用 for 处理多个文件
理解 定时执行
成功返回0,失败返回其他值。 读取上次结果,A && B 只在 A 成功时运行 B。
把和文件组合起来,即可对许多目标自动执行相同工作。
在固定时间运行。0 3 * * * 表示每天凌晨3点。
点击命令即可填入右侧终端。
说明三种方式
理解单词分割与通配
使用 set -euo pipefail
始终引用
"$var" 会展开但保留空格;'$var' 保持字面值;未的 $var 可能按空格分割并展开。
未的值会变成多个,* 或 ? 会展开成文件名,容易造成误操作。
set -euo pipefail 捕获错误、未定义和中间失败; 可提前发现问题。
点击命令即可填入右侧终端。
用 -v 查看 Node.js 版本
用 node app.js 运行 文件
用 npm 安装包并运行脚本
用 npx 在不全局安装的情况下运行一次工具
在之外(、)运行 。Web 应用、、构建和许多 编程助手都依赖它。学完 后掌握 Node,安装开发工具会轻松很多。
用 -v(或 --version)查看版本。node app.js 运行文件;node -e "console.log(1+1)" 运行一行代码。
负责安装与管理。 记录名称、版本、 与 dependencies。npm install 安装依赖;npm run start 运行脚本。 用于一次性运行。
点击命令即可填入右侧终端。
说明 是许多工具安装的前提
了解 Claude Code、Codex、Grok、 的常见安装命令
区分全局安装(-g)与一次性运行()
养成安装后检查版本的习惯
现代开发不只靠编辑器。 编程助手(Grok Build、Codex、Claude Code)、 与包管理器都在运行。第10课的 Node/ 就是起点。
官方方式可能变化,请以官方文档为准。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 等验证。
| 只使用可信官方。全局 权限出错时,优先修复 而不是 。团队与 CI 中用 devDependency 固定版本更安全。
点击命令即可填入右侧终端。
能用 -c 和 -e 执行其他语言的单行代码
能把程序保存为文件并用 python3 文件.py 运行
能用 heredoc(<<PY)把多行程序交给
能用 sed 批量修改文件中的文本
能用 awk 从表格数据中取列并汇总
能在运行 AI 给出的代码前先安全确认
只用 完成所有计算很快就会碰壁。Shell 的角色是决定"何时叫谁":计算和数据交给 Python,表格汇总交给 ,文本批量修改交给 ,再由 Shell 把结果串起来。懂 Shell,就能调用自己从没学过的语言。
多数语言都有"把代码当作直接运行"的:Python 是 -c "代码", 是 -e "代码",Perl 是 perl -e,Ruby 是 ruby -e。只要养成用 python3 -c "print(2**10)" 代替计算器的习惯,就会强大得多。
如果一段程序不是用一次就丢,就把它存成文件。把代码写进 hello.py,输入 hello.py 就能直接运行。再把第 5 课学过的 写在第一行 —— #!/usr/bin/env python3 —— 然后执行 +x hello.py 赋予,之后不用在前面加 python3,只写 ./hello.py 就能跑。运行结束后输入 就能看出是成功(0)还是失败(1),于是可以像第 8 课那样用 && 接上下一条。
程序有多行时,-c 就不方便了,这时就该用 。写 - <<'PY',从下一行起直到写着 PY 的那一行之前,都会作为整体交给 Python。中间的 - 表示"从标准输入而不是文件读取代码"。编程修改文件时经常使用的正是这种形式。
用包住结束标记(<<'PY'),正文会原封不动地传过去;不包(<<PY), 会先替换正文里的 $ 和 $()。Python 代码里很少出现 $,但或中一旦有 $ 就会悄悄出错,所以传代码时以加引号为默认做法。
'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 '' '…' 文件)。
不是,它本身就是一门语言。它按空白把每行切成 $1、$2、$3,NF 是列数,NR 是行号。基本形式是 awk '模式 { 动作 }':省略模式表示所有行,省略动作表示输出整行。开头放 BEGIN{}、结尾放 END{} 就能做准备与收尾,于是求和、平均、按项汇总都能一行搞定。
被写成从读、向标准输出写的程序之间,可以用自由连接。 sales.txt | '{print $2}' | -n | -3 就是"读文件 → 取第二列 → 按数值排序 → 只留最大的三个",一行完成。awk 与 就这样用管道相连,而 Python 则通过 -c 或 接收代码。这就是" 是指挥"的真正含义。
通常正是用这种 形式作答。粘贴之前只需确认三件事:①用眼睛读一遍它要改哪些文件;②看看有没有 或 > 这类覆盖操作;③重要文件先用 原文件 原文件.bak 备份。会读 ,就意味着能验证 AI 的答案。
点击命令即可填入右侧终端。
向用户询问一个值并存入。变量不必事先声明。
echo "你叫什么名字?"# 在屏幕上输出问题read name# 把回答读入变量 nameecho "你好,$name!"# 使用读到的值除了 , $PWD 也能告诉你。用括号 ( ) 包起来的命令在单独的 中运行,所以在里面 不会改变外面的位置。
echo "我现在在 $PWD"# 通过使用当前(cd /tmp; pwd)# 只在子 Shell 里移动 → 输出 /tmppwd# 外面仍在原来的位置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 -l# 每行一个,显示详细信息ls -t# 最近修改的排在最前ls -R# 连所有子文件夹也一起列出(递归)在 ${ } 里取出值的同时,还能截取或替换其中的一部分。这是加工值最强大的工具。
echo "${var/Some/A}"# 把第一个 Some 替换成 Aecho "${var//Some/A}"# // 会把所有 Some 都替换成 Aecho "${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 ))"# 乘方 → 1024echo "scale=2; 10/3" | bc# 小数运算 → 3.33在不同系统上的表现略有差异。 在哪里都一样,还能精确控制宽度、对齐和小数位数。
printf "你好,%s!\n" "世界"# 把值填到 %s 的位置 → 你好,世界!printf "%.2f\n" 3.14159# 保留两位小数 → 3.14printf "%05d\n" 42# 不足五位用 0 补齐 → 00042把一个值和许多模式比较时,case 比一串 if 更整洁(相当于其他语言中的 switch)。
case "$x" in# 根据 x 的值 0) echo "零";;# 值为 0 时 1) echo "一";;# 值为 1 时 *) echo "其他";; esac# * 匹配其余所有情况for 遍历列表或范围,while 在条件为真时一直,until 在条件为假时一直循环。另外还有 C 风格的 for。
for ((i=1; i<=3; i++)); do echo "$i"; done# C 风格的 forwhile (( 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让接受 -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 ./lib/helpers.sh# 把另一个文件的函数和变量载入当前 Shell. ~/.bashrc# . 是 source 的简写export API_KEY="abc123"# 让子进程也能看到它加上, 会强大得多。可以组合递归搜索、行号、排除和计数。
grep -r "TODO" ./src# -r:递归搜索整个文件夹grep -n "error" app.log# -n:带上行号grep -v "debug" app.log# -v:只显示不含该词的行(反向)grep -c "error" app.log# -c:只显示匹配的行数在文本流过时进行编辑。它能替换、删除和选取范围,-i 会直接修改文件本身(请保留备份)。
sed 's/okay/great/g' file.txt# 把所有 okay 换成 greatsed '/^#/d' file.txt# 删除以 # 开头的注释行sed -i.bak 's/old/new/g' file.txt# 直接修改文件 + 留下 .bak 备份sed -n '/error/p' log.txt# 只输出含有 error 的行按空格(或 -F 指定的字符)把每行切开,把各段当作列 $1、$2 … 来处理。它擅长求和、筛选和统计。
echo 'a b c' | awk '{print $2}'# 第二列 → bawk -F',' '{print $3}' data.csv# 按逗号切分,取第三列awk -F',' '$2 > 25' people.csv# 第二列大于 25 的行awk '{s+=$1} END{print s}' nums.txt# 第一列的合计用把小工具连起来,就能做强大的数据处理。 把一条的输出变成下一条命令的。
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)<< EOF()把多行文字整体交给作为输入。<<<()则是送入一行短文字的轻便方法。
cat << EOF# 到 EOF 为止的几行成为输入多行
文字
EOF# 两个 EOF 之间的内容就是正文grep "香蕉" <<< "苹果 香蕉 葡萄"# 用 <<< 输入一行(stdout)和标准错误(stderr)走的是不同的通道。2> 只接收错误,2>&1 把错误送到和输出相同的地方,/dev/null 是专门丢弃东西的地方。
command 2> error.log# 只把错误信息写入文件command > out.log 2>&1# 输出和错误一起写入 out.logcommand > /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 设定收到(退出、错误、中断)时要运行的。用来清理临时文件尤其方便。
TMP=$(mktemp)# 安全地创建临时文件cleanup() { rm -f "$TMP"; }# 清理用的trap cleanup EXIT# 脚本结束时总会清理trap 'echo 已中断; exit 1' SIGINT# 按下 Ctrl-C 也能安全处理在开头写上 set ,脚本就更不怕出错。-e(出错即停)、-u(禁止使用未设置的)和 -o pipefail(察觉中的失败)一起使用。-x 用于。
set -euo pipefail# 稳健脚本的标准第一行set -x# 逐条输出正在运行的(调试)set +x# 关闭调试在后面加上 &,它就作为运行。jobs 列出这些任务,wait 等到它们全部结束。
sleep 5 &# 在后台运行jobs# 仍在运行的后台任务列表wait# 等到所有后台任务都结束time sleep 1# 测量命令用了多长时间真实中反复出现的防御模式:检查必需的值、检查是否存在、失败时立即停止。
: "${VAR:?必须设置 VAR}"# 缺少 VAR 时报错并停止command -v jq && echo "已找到 jq"# 检查命令是否已安装cp a b || { echo 失败; exit 1; }# 失败时输出提示并停止set -euo pipefail 是三个的组合。知道每一个能防止什么事故,就明白它为什么成了标准写法。
set -e# 只要有失败就立即停止set -u# 使用未定义的会报错(能发现拼写错误)set -o pipefail# 中间一步失败,整个管道就算失败调整文件名的匹配方式()。globstar 让 ** 深入子文件夹,nullglob 在没有匹配时给出空值。
shopt -s globstar# ** 也能匹配到子文件夹里( 4+)for f in **/*.sh; do echo "$f"; done# 所有子文件夹中的每个 .sh 文件shopt -s nullglob# 没有匹配时给出空值,而不是模式原文(内部字段分隔符)决定单词分割时在哪里切开。要安全地逐行读取文件,就把 IFS= 和 read -r 一起用。
IFS=',' read -ra f <<< "a,b,c"# 按逗号切分,存入 fwhile IFS= read -r line; do# 保留空格和特殊字符 echo "$line"; done < file.txt# 安全地一次读取一行不同的项目可能需要不同版本的 Node。 可以安装多个版本并在它们之间切换。
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash# 安装 nvm(版本号请查看官方文档)nvm install 22# 安装 Node 22nvm use 22# 在当前 中使用 Node 22node -v# 确认切换后的版本中的 运行时会把 _modules/.bin 加进 ,所以不用全局安装也能使用项目里的工具。
npm init -y# 快速生成 package.jsonnpm install lodash# 添加运行时依赖npm install -D typescript# 只在开发时使用的依赖npm run build# 运行 scripts.build想不全局安装、只运行一次最新版本的工具时,用 。对版本经常变化的 尤其有用。
npx create-next-app@latest my-app# 搭建项目骨架的示例npx prettier --write .# 运行 prettier(本地的或下载的)npx --yes cowsay hello# 不询问确认,直接运行一次用官方安装或全局 包来安装。装好后立刻用版本检查。
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# 检查安装(示例)用于部署、登录和托管的 ,常和快速的包管理器 pnpm 一起安装。
npm install -g firebase-tools# Firebase CLIfirebase login# 通过登录firebase projects:list# 项目列表npm install -g pnpm# 全局安装 pnpm如果安装成功却找不到,那就是 的问题。用 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让 修改代码时,得到的答案几乎总是这种形式:用 传入一小段 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 结束——必须顶格写在行首在中生成多行的配置或文档时, 也是最整洁的办法。标记不加时,$ 会当场被替换成值。
cat <<EOF > .env# 标记不加引号 → 变量会被替换PORT=$PORT# $PORT 以实际的值保存EOF# 到这里结束cat <<'EOF' > template.txt# 加了引号 → $PORT 保持原样bash <<< "echo one-liner"# 用 只传一行在前面加上地址(行号或),就只改那些行。用 -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 '{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 就成了计算器用 处理,“对找到的每个结果运行”用 。两个都会用,能用连起来的范围就大大扩展了。
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)重新编写。部分命令仅供参考。