玩转 Linux 命令行:文本过滤器入门
神奇的文本“过滤器”!
化繁为简,将原始数据变为有用信息。
引言
Linux 有一个非常核心的设计哲学:每个工具只做一件事,并把它做到极致。我们可以像搭积木一样,将这些小工具自由组合,搭建出功能强大的“城堡”。
在本章节中,我们将认识一些基础的“小积木”——文本过滤器。稍后,在更进阶的章节里,我们会学习如何将它们串联起来,完成更复杂的自动化任务。
别看这篇文章有点长,它大部分内容都是示例,所以请放轻松,并没有看起来那么吓人。
那么,什么是过滤器?
在 Linux 命令行中,“过滤器”(Filter)就是一个程序,它接收文本数据作为输入,经过一系列处理后,再输出处理过的新文本数据。
想象一个漏斗,你把一堆混杂着沙子和石头的混合物倒进去,漏斗会帮你把沙子筛出来。这里的“漏斗”就是过滤器。它能帮你从海量原始数据中,提取、整理、转换出你真正需要的信息。
这些过滤器通常都带有丰富的命令行选项,可以微调它们的功能。所以,遇到问题时,随时查阅 man 手册(man 命令名)是个好习惯。
在下面的例子中,我们会从一个文件中读取数据。但在后续章节学习了“管道和重定向”后,你将解锁更多强大的数据输入方式。
让我们开始吧!下面的例子只是这些命令功能的冰山一角,请务必发挥你的创造力,多多尝试。
为了方便演示,我们先创建一个名为 sales.txt 的示例文件,内容如下。你可以把它想象成一个简单的销售记录。
# 使用 cat 命令查看文件内容
$ cat sales.txt
张三 苹果 20
李四 橙子 5
王五 西瓜 12
赵六 梨 4
孙七 橙子 9
周八 桃子 7
李四 橙子 12
王五 葡萄 39
吴九 芒果 7
郑十 菠萝 3
钱一 哈密瓜 2
冯二 青柠 14
head - 只看开头
head 命令就像它的名字一样,只显示文件或数据流的“头部”内容。默认情况下,它会显示前 10 行,但你可以通过参数指定行数。
语法: head [-n 行数] [文件路径]
示例1:默认显示前10行
$ head sales.txt
张三 苹果 20
李四 橙子 5
王五 西瓜 12
赵六 梨 4
孙七 橙子 9
周八 桃子 7
李四 橙子 12
王五 葡萄 39
吴九 芒果 7
郑十 菠萝 3
示例2:指定只显示前4行
$ head -n 4 sales.txt
张三 苹果 20
李四 橙子 5
王五 西瓜 12
赵六 梨 4
小提示:
-n 4也可以简写为-4。
tail - 只看结尾
tail 与 head 正好相反,它用于显示文件或数据流的“尾部”内容。默认也是显示最后 10 行。
语法: tail [-n 行数] [文件路径]
示例1:默认显示最后10行
$ tail sales.txt
王五 西瓜 12
赵六 梨 4
孙七 橙子 9
周八 桃子 7
李四 橙子 12
王五 葡萄 39
吴九 芒果 7
郑十 菠萝 3
钱一 哈密瓜 2
冯二 青柠 14
示例2:指定只显示最后3行
$ tail -n 3 sales.txt
郑十 菠萝 3
钱一 哈密瓜 2
冯二 青柠 14
tail还有一个非常有用的功能tail -f,可以实时监控文件的新增内容,常用于查看日志文件。
sort - 排序
sort 命令用于对输入的数据进行排序。默认按字母(字典)顺序排序,但它有非常多的选项来控制排序规则。
语法: sort [选项] [文件路径]
示例:按默认规则排序
$ sort sales.txt
冯二 青柠 14
李四 橙子 12
李四 橙子 5
钱一 哈密瓜 2
孙七 橙子 9
王五 葡萄 39
王五 西瓜 12
吴九 芒果 7
张三 苹果 20
赵六 梨 4
郑十 菠萝 3
周八 桃子 7
注意:
sort默认是按整行从第一个字符开始比较的。对于数字,"12" 会排在 "5" 的前面,因为它只看第一个字符 '1' 和 '5'。如果想按数值大小排序,可以使用-n选项。
nl - 添加行号
nl (Number Lines) 命令的功能很简单:为输入的每一行文本添加行号。
语法: nl [选项] [文件路径]
示例:添加默认行号
$ nl sales.txt
1 张三 苹果 20
2 李四 橙子 5
3 王五 西瓜 12
4 赵六 梨 4
5 孙七 橙子 9
6 周八 桃子 7
7 李四 橙子 12
8 王五 葡萄 39
9 吴九 芒果 7
10 郑十 菠萝 3
11 钱一 哈密瓜 2
12 冯二 青柠 14
默认格式可能不是我们想要的,可以用选项来美化它。
示例2:自定义格式
$ nl -s '. ' -w 3 sales.txt
1. 张三 苹果 20
2. 李四 橙子 5
3. 王五 西瓜 12
4. 赵六 梨 4
5. 孙七 橙子 9
6. 周八 桃子 7
7. 李四 橙子 12
8. 王五 葡萄 39
9. 吴九 芒果 7
10. 郑十 菠萝 3
11. 钱一 哈密瓜 2
12. 冯二 青柠 14
-s '. ':指定行号后面的分隔符为“点+空格”。因为包含了空格,我们用单引号'把它包起来,告诉命令行这是一个整体。-w 3:指定行号占用的宽度为3个字符。
wc - 统计计数
wc (Word Count) 不仅能统计单词,还能统计行数和字符数。
语法: wc [选项] [文件路径]
示例1:显示全部统计信息
$ wc sales.txt
12 36 195 sales.txt
输出的三个数字依次代表:行数(12)、单词数(36)、字节数(195)。
示例2:只统计行数
# -l 表示 lines
$ wc -l sales.txt
12 sales.txt
示例3:同时统计行数和单词数
# -w 表示 words
$ wc -lw sales.txt
12 36 sales.txt
常用选项:
-l(行数),-w(单词数),-c(字节数),-m(字符数)。
cut - 切分提取
如果你的数据是按列组织的(比如用空格、逗号或制表符分隔),cut 命令可以帮你精准地“切”出你想要的列。
语法: cut [选项] [文件路径]
我们的示例文件有3列:姓名、水果、数量。它们之间用空格分隔。
示例1:只提取第一列(姓名)
$ cut -d ' ' -f 1 sales.txt
张三
李四
王五
赵六
孙七
周八
李四
王五
吴九
郑十
钱一
冯二
-d ' ':指定分隔符(delimiter)为空格。cut默认使用Tab键作为分隔符,所以当数据是其他分隔符时,必须用-d显式指定。-f 1:指定提取第 1 个字段(field)。
示例2:提取第1列和第3列
$ cut -d ' ' -f 1,3 sales.txt
张三 20
李四 5
王五 12
赵六 4
孙七 9
周八 7
李四 12
王五 39
吴九 7
郑十 3
钱一 2
冯二 14
sed - 替换大师
sed (Stream Editor,流编辑器) 是一个极其强大的文本处理工具,最常见的用法就是进行查找和替换。
语法: sed 's/查找内容/替换内容/g' [文件路径]
这个表达式是 sed 的核心:
s:表示执行替换(substitute)操作。- 三个
/:是分隔符,用来划分“查找内容”和“替换内容”。 g:表示全局(global)替换,即替换行内的所有匹配项。如果省略g,则只替换每行遇到的第一个匹配项。
示例:把所有的“橙子”都换成“香蕉”
$ sed 's/橙子/香蕉/g' sales.txt
张三 苹果 20
李四 香蕉 5
王五 西瓜 12
赵六 梨 4
孙七 香蕉 9
周八 桃子 7
李四 香蕉 12
王五 葡萄 39
吴九 芒果 7
郑十 菠萝 3
钱一 哈密瓜 2
冯二 青柠 14
重要提示:
sed以及我们介绍的其他过滤器,默认情况下不会修改原始文件,它们只是把处理后的结果打印到屏幕上。这非常安全!如果你想保存结果,需要使用“重定向”技术,我们以后会学到。
uniq - 去除重复
uniq (Unique) 命令用于移除数据中连续的重复行。请注意“连续”这个关键词,这是 uniq 的一个重要特点。
语法: uniq [选项] [文件路径]
假设我们的 sales.txt 文件因为程序错误,产生了一些连续的重复记录:
# 新的 sales_with_duplicates.txt 文件
$ cat sales_with_duplicates.txt
张三 苹果 20
李四 橙子 5
李四 橙子 5
李四 橙子 5
王五 西瓜 12
赵六 梨 4
王五 葡萄 39
王五 葡萄 39
吴九 芒果 7
示例:使用 uniq 去除重复
$ uniq sales_with_duplicates.txt
张三 苹果 20
李四 橙子 5
王五 西瓜 12
赵六 梨 4
王五 葡萄 39
吴九 芒果 7
如果重复的行不相邻,
uniq是无法识别的。怎么办呢?聪明的你可能想到了:可以先用sort把文件排序,让所有重复的行都挨在一起,然后再用uniq处理!这就是命令组合的威力。
tac - 倒序输出
Linux 程序员有时候有点冷幽默。tac 这个命令就是 cat 的倒写,它的功能也和 cat 正好相反:它会从最后一行开始,反向逐行输出文件内容。
语法: tac [文件路径]
假设我们的销售记录是按时间顺序追加到文件末尾的,最新的记录在最下面。如果我们想让最新的记录显示在最上面,tac 就派上用场了。
示例:反向显示文件内容
$ tac sales.txt
冯二 青柠 14
钱一 哈密瓜 2
郑十 菠萝 3
吴九 芒果 7
王五 葡萄 39
李四 橙子 12
周八 桃子 7
孙七 橙子 9
赵六 梨 4
王五 西瓜 12
李四 橙子 5
张三 苹果 20
进阶神器
除了上面介绍的这些,还有两个更强大的文本处理工具,它们几乎可以完成任何你想象得到的文本处理任务,但学习曲线也更陡峭一些。有兴趣的话可以自行探索:
grep: 强大的文本搜索工具,用于根据模式(正则表达式)查找行。awk: 一种编程语言,专门用于处理和分析结构化文本(按列组织的数据)。
总结
head: 查看文件开头的若干行。tail: 查看文件结尾的若干行。sort: 对文本行进行排序。nl: 为文本行添加行号。wc: 统计行数、单词数和字符数。cut: 按列切分并提取文本。sed: 对文本进行查找和替换。uniq: 移除连续的重复行。tac: 反向输出整个文件。- 核心思想: 过滤器让我们能够像流水线一样处理数据,每个工具完成一个简单任务。
man手册: 别忘了,man是你最好的老师,可以查看命令的所有选项和用法。
动手练习
光说不练假把式,现在轮到你了!
- 仿照上面的例子,创建你自己的数据文件(比如一个班级的成绩单、购物清单等)。
- 对你的文件挨个使用上面介绍的所有命令,熟悉它们的基本功能。
- 为你感兴趣的命令(比如
sort或cut)查阅man手册,尝试至少 2 个本文没有提到的命令行选项,看看它们会产生什么效果。