在 Debian/Ubuntu 系统中,默认的 awk 通常链接到 mawk,因为它的轻量级优势。
ls $(readlink -f $(which awk))
/usr/bin/mawk
AWK (/ɔːk/) is a scripting language designed for text processing and typically used as a data extraction and reporting tool. Like sed and grep, it is a filter, and it is a standard feature of most Unix-like operating systems. The shell command that runs the AWK processor is named awk.
AWK 并不是一个普通单词的缩写,而是三位开发者姓氏的首字母组合。
- Aho (Alfred Aho)
- Weinberger (Peter Weinberger)
- Kernighan (Brian Kernighan)
他们共同创造了这种常用于 Linux/Unix 下对文本和数据进行结构化扫描与处理的编程语言。
mawk (Mike’s AWK)
- 哲学:速度至上,极致精简。
- 特点:它基于字节码解释器,是目前运行速度最快的 AWK 实现。
- 优势:在处理巨大的文本文件(GB 级别)时,
mawk的性能通常比gawk高出数倍。它的二进制文件非常小,适合嵌入式或容器环境。 - 缺点:功能比较保守,严格遵循 POSIX 标准,缺乏现代扩展功能。
gawk (GNU AWK)
- 哲学:功能全家桶,标准制定者。
- 特点:它是 GNU 项目的一部分,也是目前功能最强、应用最广的实现。
- 优势:支持大量扩展功能(如 TCP/IP 网络操作、正则表达式捕获组、双向管道、多字节字符集/UTF-8 支持)。
- 缺点:由于功能繁多,它比
mawk慢,且二进制体积更大。
关键差异点
| 特性 | mawk | gawk |
|---|---|---|
| 执行速度 | 极快 (通常是第一名) | 一般 (较慢) |
| UTF-8 支持 | 较差 (常将多字节字符当字节处理) | 完美支持 |
| 正则表达式 | 基础 POSIX 扩展 | 极其丰富 (支持 \s, \w 等) |
| 网络功能 | 无 | 支持通过 /inet/tcp/... 读写网络 |
| 调试器 | 无 | 自带 gawk --debug |
| 数组排序 | 需手写算法 | 提供内置函数 asort() |
如果系统中没有 gawk,安装它:
apt install gawk
安装后,Debian 系系统会自动通过 update-alternatives 将默认 awk 指向 gawk。如果没变,可以手动切换:
update-alternatives --set awk /usr/bin/gawk
Perl
Perl 最初的设计目标之一就是为了取代 awk 和 sed。
Perl借用了C、sed、awk、shell脚本、Lisp以及很多其他编程语言的特性。其中最重要的特性是Perl内部集成了正则表达式的功能,以及巨大的第三方代码库CPAN。
冷知识:awk 的很多逻辑被直接吸收到了 Perl 语法中。
如果你发现 awk 的脚本写到几十行太复杂了,通常该换成 Perl 或 Python。
PCRE2
从名字就能看出它们渊源颇深:PCRE2 的全称是 Perl Compatible Regular Expressions(Perl 兼容正则表达式库)。
简单来说,Perl 是这种正则语法的“母体”和“定义者”,而 PCRE2 是为了让其他语言(如 C、C++、Nginx、Apache)也能使用这种强大语法的“独立实现库”。
- 起源(Perl):Larry Wall 在开发 Perl 语言时,设计了一套极其强大且灵活的正则表达式语法。由于太好用了,程序员们希望在不运行整个 Perl 解释器的情况下,也能在 C 语言程序里用这种语法。
- 诞生(PCRE):Philip Hazel 开发了 PCRE 库,用 C 语言重写了 Perl 的正则逻辑,使其成为一个轻量级的第三方库。
- 进化(PCRE2):随着时间推移,原有的 PCRE(现在叫 PCRE1)架构逐渐老旧。2015 年,官方发布了 PCRE2,这是目前的标准版本,性能更强,API 更加现代化且安全。
- PCRE2 的目标是尽可能完全兼容 Perl 的正则语法。如果你在 Perl 里写一个
/(?<name>\w+)/(命名捕获组),在 PCRE2 里几乎可以原封不动地运行。 - PCRE2 是一个标准的 C 动态链接库(
.so或.dll)。它并不依赖 Perl,也不包含 Perl 的逻辑,它只负责“理解并执行 Perl 风格的正则”。
为什么 Nginx 编译时经常看到它们?
- PCRE2 的作用(必须):Nginx 的
location匹配、rewrite跳转、referer过滤等核心功能全靠 PCRE2。没有它,Nginx 就失去了处理复杂 URL 的能力。这就是为什么./configure时通常需要指定--with-pcre。
grep
作为一个天天在终端里敲 grep 的系统工程师,你可能已经把它当成了一个肌肉记忆,但它的名字其实源自 1970 年代 Unix 鼻祖级编辑器 ed(Editor)的一个具体操作命令。
grep 实际上是三个单词首字母的缩写组合:g/re/p。
在最早的 ed 编辑器中,如果你想在整个文件里搜索某个特定模式并打印出来,你需要输入以下指令:
- g (Global):表示全局搜索,即扫描整个文件,而不是只看当前一行。
- /:这是分隔符。
- re (Regular Expression):表示正则表达式。这里是你想要搜索的内容模式。
- /:闭合分隔符。
- p (Print):表示打印。即把匹配到的行显示在屏幕上。
合起来就是:Global Regular Expression Print(全局正则表达式打印)。
它是怎么从“命令”变成“软件”的?这个故事很有“黑客精神”:
- 需求诞生:当时 Unix 的创始人之一 Ken Thompson 的同事需要一个能从文件里抓取特定内容的工具。
- 快速成型:Ken Thompson 觉得既然
ed里已经有这个逻辑了,干脆把这段代码抽出来,封装成一个独立的命令行程序。 - 命名:他直接用了
ed里的那个指令g/re/p作为文件名,于是grep就诞生了。
理解了 g/re/p 的含义,你就很容易理解它的变体了:
- egrep (Extended grep):支持更复杂的扩展正则表达式。
- fgrep (Fixed grep):只搜索固定字符串,不支持正则,但速度极快。
- pgrep (Process grep):基于名字搜索进程 ID。
在英语中,grep 已经从一个缩写变成了一个动词。
就像你会说“Google 一下”一样,开发者们常说:“Can you grep the logs for that error ID?”(你能在大堆日志里搜索一下那个错误 ID 吗?)
- 标签 awk