AWK & SED 生产力教程 / 第 1 章:AWK/SED 入门导论
第 1 章:AWK/SED 入门导论
每一个 Unix 工具都遵循一个哲学:做一件事,并把它做好。AWK 和 SED 是这个哲学最完美的诠释。
1.1 历史渊源
SED 的诞生
SED(Stream EDitor,流编辑器)诞生于 1974 年,由贝尔实验室的 Lee McMahon 开发。它是最早的 Unix 文本处理工具之一,设计初衷是成为 ed 行编辑器的流式版本。
时间线:
1969 Unix 诞生(Ken Thompson, Dennis Ritchie)
1973 ed 编辑器成熟
1974 SED 诞生(Lee McMahon)
1977 AWK 诞生(Aho, Weinberger, Kernighan)
1985 Perl 诞生(Larry Wall,受 AWK 影响)
2004 GNU sed 4.0 发布
AWK 的诞生
AWK 于 1977 年在贝尔实验室诞生,名字来源于三位创造者的姓氏首字母:
| 字母 | 创造者 | 贡献 |
|---|---|---|
| A | Alfred Aho | 编译器理论,正则表达式 |
| W | Peter Weinberger | 数据库系统 |
| K | Brian Kernighan | C 语言联合创造者,《AWK 程序设计语言》作者 |
AWK 最初的设计目标是:让程序员能够在命令行上用一行代码完成数据提取和格式化。
💡 趣闻:Brian Kernighan 后来承认,他从未想到 AWK 会被使用超过 40 年。但它的设计简洁到"恰到好处",至今仍是文本处理的标准工具。
1.2 设计哲学
Unix 管道哲学
stdin stdout
数据 → [SED] → [AWK] → [sort] → [uniq] → 结果
流式处理,每个工具专注一件事
Unix 工具的核心理念:
| 原则 | 说明 | 体现 |
|---|---|---|
| 单一职责 | 每个工具只做一件事 | SED 编辑流,AWK 格式化输出 |
| 组合使用 | 通过管道连接 | `cat file |
| 文本接口 | 一切皆文本 | 输入输出都是文本流 |
| 沉默是金 | 没有错误就是成功 | 只输出有结果的内容 |
SED 的设计哲学
SED 是一个面向行的流编辑器:
输入流 → 逐行读取 → 对匹配行执行命令 → 输出
↑
不修改原文件(除非 -i)
核心设计:
- 流式处理:一次读一行,处理完就输出,不占用额外内存
- 非交互式:适合脚本和管道中使用
- 原地编辑:
-i选项可以直接修改文件
AWK 的设计哲学
AWK 是一个面向数据的文本处理语言:
输入 → 分割成字段 → 模式匹配 → 执行动作 → 格式化输出
↑
自动解析结构化文本
核心设计:
- 数据驱动:根据数据模式决定执行什么操作
- 字段自动分割:自动将每行拆分成字段
- 隐式循环:自动对每一行执行规则
1.3 适用场景
SED 最擅长的事
| 场景 | 示例 | 命令 |
|---|---|---|
| 批量替换 | 把配置文件中的端口改掉 | sed -i 's/8080/9090/g' config.yml |
| 删除行 | 去掉空行和注释 | sed '/^#/d; /^$/d' file |
| 插入内容 | 在文件头部添加说明 | sed '1i\# Auto-generated' file |
| 原地编辑 | 修改多个文件 | sed -i 's/old/new/g' *.conf |
| 提取行段 | 截取两个标记之间的内容 | sed -n '/START/,/END/p' file |
AWK 最擅长的事
| 场景 | 示例 | 命令 |
|---|---|---|
| 字段处理 | 提取日志中的 IP 和状态码 | awk '{print $1, $9}' access.log |
| 统计汇总 | 计算某列的总和/平均值 | awk '{sum+=$3} END{print sum}' data.csv |
| 条件过滤 | 筛选错误日志 | awk '$9 >= 500' access.log |
| 报表生成 | 格式化输出数据 | awk '{printf "%-20s %10d\n", $1, $2}' |
| 数据转换 | CSV 转 TSV | awk -F, '{OFS="\t"; $1=$1}1' file.csv |
何时用 SED,何时用 AWK?
需要做的事 →
只做简单的替换/删除? → SED
需要处理字段(列)? → AWK
需要统计/计算? → AWK
需要复杂的条件判断? → AWK(或 Python)
需要逐行正则替换? → SED
需要两者结合? → 管道连接
1.4 与 Python 的对比
相同任务的不同写法
任务 1:统计文件行数
# SED
sed -n '$=' file.txt
# AWK
awk 'END{print NR}' file.txt
# Python
python3 -c "
count = 0
with open('file.txt') as f:
for _ in f:
count += 1
print(count)
"
任务 2:提取日志中的 IP 地址并统计出现次数
# AWK(一行搞定)
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10
# Python(需要更多代码)
python3 -c "
from collections import Counter
with open('access.log') as f:
ips = [line.split()[0] for line in f]
for ip, count in Counter(ips).most_common(10):
print(f'{count:>8} {ip}')
"
任务 3:将 CSV 中价格大于 100 的行提取出来
# AWK
awk -F, '$3 > 100' products.csv
# Python
python3 -c "
import csv
with open('products.csv') as f:
reader = csv.reader(f)
for row in reader:
if float(row[2]) > 100:
print(','.join(row))
"
性能对比
处理一个 1GB 的日志文件(约 1000 万行):
| 操作 | AWK/SED | Python | 说明 |
|---|---|---|---|
| 简单过滤 | 3-5 秒 | 8-12 秒 | AWK 快 2-3 倍 |
| 字段提取 | 4-6 秒 | 10-15 秒 | AWK 自动分割优势 |
| 正则替换 | 5-8 秒 | 12-18 秒 | SED 流式处理优势 |
| 复杂统计 | 8-15 秒 | 6-10 秒 | Python 可能更快 |
| 多步处理 | 15-25 秒 | 10-15 秒 | Python 单进程更优 |
💡 经验法则:行数多、逻辑简单的任务用 AWK/SED;逻辑复杂、需要数据结构的任务用 Python。
选择建议
┌─ 一行命令/管道?──→ AWK/SED
│
你的需求是什么?──→├─ 处理结构化数据(JSON/XML)?──→ Python
│
├─ 需要错误处理/日志/测试?──→ Python
│
└─ 系统管理/DevOps 自动化?──→ AWK/SED + Shell
1.5 快速上手
你的第一个 SED 命令
# 创建测试文件
echo -e "Hello World\nHello Linux\nGoodbye World" > hello.txt
# 将 Hello 替换为 Hi
$ sed 's/Hello/Hi/' hello.txt
→ Hi World
→ Hi Linux
→ Goodbye World
你的第一个 AWK 命令
# 创建测试文件
echo -e "Alice 90 85 92\nBob 78 82 88\nCarol 95 91 87" > scores.txt
# 打印每行的第一列(名字)和第三列(第二门成绩)
$ awk '{print $1, $3}' scores.txt
→ Alice 85
→ Bob 82
→ Carol 91
一个实用的管道组合
# 统计当前目录下各类型文件的数量
$ find . -type f | sed 's/.*\.//' | sort | uniq -c | sort -rn
→ 125 md
→ 42 html
→ 18 css
→ 7 js
分解:
find . -type f— 列出所有文件sed 's/.*\.//'— 提取文件扩展名sort— 排序(uniq 需要有序输入)uniq -c— 统计每种扩展名出现次数sort -rn— 按数量降序排列
1.6 版本差异速查
GNU vs BSD 差异
| 特性 | GNU (Linux) | BSD (macOS) | 建议 |
|---|---|---|---|
| SED 原地编辑 | sed -i 's/old/new/' file | sed -i '' 's/old/new/' file | macOS 需要空字符串参数 |
| SED 扩展正则 | sed -E 或 sed -r | sed -E | 用 -E 最兼容 |
| AWK 版本 | gawk | nawk / awk | 复杂功能用 gawk |
| AWK 数组 | 关联数组 | 关联数组 | 相同 |
| AWK 函数 | 自定义函数 | 自定义函数 | 相同 |
⚠️ macOS 用户注意:安装 GNU 工具后建议设置别名,避免踩坑:
brew install gnu-sed gawk echo 'alias sed="gsed"' >> ~/.zshrc echo 'alias awk="gawk"' >> ~/.zshrc
1.7 学习建议
学习路径
Week 1: SED 基础 → AWK 基础 → 正则表达式
↓
Week 2: SED 进阶 → AWK 进阶 → 文本处理实战
↓
Week 3: 管道组合 → 日志分析 → 报告生成
↓
Week 4: 脚本编写 → 性能优化 → 最佳实践
学习方法
- 动手为王:每个示例都要亲手敲一遍
- 从小处开始:先用一个命令解决一个小问题
- 管道思维:把复杂问题分解成多个简单步骤
- 查阅手册:
man awk、man sed、info awk是最好的参考 - 积累片段:建立自己的常用命令片段库
📌 记住:不需要记住所有语法,只需要知道"能做什么",细节查手册即可。
扩展阅读
- 《The AWK Programming Language》— Alfred V. Aho 等著,AWK 的"圣经"
- 《sed & awk》— Dale Dougherty & Arnold Robbins 著,O’Reilly 经典
- GNU SED Manual
- GNU AWK Manual
- AWK One-Liners Explained
- SED One-Liners Explained
下一章:第 2 章:SED 基础 — 掌握流编辑器的核心操作。