对话 UNIX,第 9 部分: 正则表达式

非常奇怪,直到今天我仍然能重复周六早上的经典歌曲“Conjunction Junction 。这是好事(看了太多电视)还是坏事(也许是我现在职业的先兆)仍然有待讨论 。不管怎样,这首小调在欢快的节奏下传递了基本的信息 。
我还没有为学习 Unix 构想出与“Conjunction Junction相似的作品,但是我会在未来的几个月里尝试亲手编写这样的歌曲 。与此同时,趁着快乐回忆所带来的好心情,我们继续以 Schoolhouse 摇滚的传统学习方式攻克命令行 。
现在开始上课 。吐出嘴里的口香糖,回到您的座位上,然后拿出一根二号铅笔 。还有您,Spicoli 。
模仿秀
您可以将 UNIX 命令行看作是一句话:
可执行命令,如 cat 或 ls,是动词——操作 。
命令的输出是名词——要查阅或使用的数据 。
Shell 操作符,如 |(管道)或 >(重定向标准输出),是连词——用于连接句子 。
例如,命令行:ls -A | wc -l 用于计算当前目录下的条目数(忽略特殊条目 . 和 ..),它包含两个句子 。第一个句子 ls -A 是动词结构,列举当前目录下的内容,第二个句子 wc -l 是另一个动词结构,用于计算行数 。第一个句子输出的结果作为第二个句子的输入,并由连接词(管道)连接这两个句子 。
在本系列文章以及其他文章中展示的许多您可能已经学习过的命令行句式都具有这种句子结构 。
但是,如果缺少了文法上的修饰语,命令行将显得不专业 。当然,基本句子也能完成工作,但是这样显得不优美 。(在此对高中英语演唱二人组 Rad 女士和 Perlstein 女士表示歉意 。)解决更有趣的问题需要用到形容词 。
几乎所有重要问题都需要从无用数据中过滤出有用数据 。虽然属性的数量和种类会有所不同,但是每种方案都通过某种方式(形式或格式),隐式或显式地描述了它要查找并处理的信息,从而生成另外一种形式的其他信息 。
在命令行中,正则表达式 的作用相当于形容词——一种描述或限定词 。在应用到输出时,正则表达式可辨别相关数据和无关数据 。
标点概述
让我们看一个示例问题 。
grep 实用工具逐行过滤输入并寻找匹配 。grep 的最简单应用是打印那些包含与某个模式匹配的文本的行 。grep 可以查找具有固定顺序的字符组合,甚至可以通过使用 -i 选项来忽略大小写 。
因此,假定文件 heroes.txt 包含以下行:
Catwoman
Batman
The Tick
Spider Man
Black Cat
Batgirl
Danger Girl
Wonder Woman
Luke Cage
The Punisher
Ant Man
Dead Girl
Aquaman
SCUD
Spider Woman
Blackbolt
Martian Manhunter
命令行:
grep -i man heroes.txt
将生成:
Catwoman
Batman
Spider Man
Wonder Woman
Ant Man
Aquaman
Martian Manhunter
其中 grep 扫描 heroes.txt 文件中的每一行并查找字母 m,后面紧跟 a,然后紧跟 n 。除了必须保证相邻,这些字母可以出现在行的任何位置,甚至可以位于较大的单词中间 。在不考虑大小写的情况下(-i 选项),Catwoman、Batman、Spider Man、Wonder Woman、Ant Man、Aquaman 和 Martian Manhunter 都包含字符串 man 。
【对话 UNIX,第 9 部分: 正则表达式】grep 实用工具包含其他可优化搜索的内置选项 。例如,-w 选项限制于匹配整个单词,因此 grep -i -w man 将排除 Catwoman 和 Batman(举例来说) 。
该工具还有一个优秀的功能,可以排除而不是包括所有匹配的搜索结果 。使用 -v 选项来排除 匹配的行 。例如:
grep -v -i 'spider' heroes.txt
将打印除了包含字符串 spider 之外的所有行 。

推荐阅读