『Linux学习笔记』7. 管道和过滤器 -- pipe

在Linux中, 管道(pipe)可以将一个命令的标准输出送往另一个命令的标准输入, 多个管道可以组成管道线(pipeline).

管道操作符

与重定向类似, 管道也拥有自己的操作符"|", 当多个命令使用"|"连接时, 就意味着它们位于同一管道中, 它们的标准输出与标准输入会依次相连.

ls | less

上面这行代码中, ls所获取的当前目录内容将被传入less打开而非直接送往标准输出(屏幕)

 

文本过滤命令

在使用中, 管道通常会将多个指令连接在一起以完成复杂的操作, 而过程中不乏对文本数据进行操作的指令, 如筛选\查重\统计\分割等, 而这类命令就是"文本过滤命令"或被称为"过滤器".

下面将依次介绍常用的过滤器并举例说明:

grep

grep是常用的筛选命令之一, 它可以在输入数据中匹配关键字. 若成功匹配, 它将会高亮显示成功的匹配关键字并输出关键字所在的行.

grep keyword [file...]

上方keyword指需要匹配的关键字, file指grep的输入, 若file不指定则为系统标准输入(键盘); 若grep在管道中, 则grep的输入为上一命令的标准输出.

下面将通过两组指令来帮助建立管道和grep的概念:

ls -a ~ | grep bash

再与下述指令的执行结果对比一下:

ls -a ~

经过上面的例子不难发现, 第一组指令中的"ls -a"指令的标准输出没有被送到系统默认的标准输出上(屏幕), 而是通过管道送往了下一指令grep的标准输入中, 最终标准输出(屏幕)得到的结果则是"grep"在当前目录下匹配到"bash"关键词的所有行;

 

uniq

当我们获得了大量数据时, 有时会希望找出或过滤掉重复的内容, 这时就需要用到uniq命令.

与其他过滤器相似, uniq也常被用在管道线中;

在默认状态下, uniq会删除所有重复的行, 像这样:

ls -a ~ | uniq

上述命令将会输出所有在当前用户的home目录下的非重复文件或文件夹.

 

有时, 我们不希望重复的内容被删除, 而是希望将其标注出来, 那么可以选择在使用uniq时加上-d参数

ls -a ~ | uniq -d

这样, 重复的行将会被高亮显示而非直接移除.

 

sort

我们手上的数据并非总是有序的, 这时就需要使用sort命令对数据进行排序.

如我们使用ls命令同时获取多个目录下的文件时, 我们拿到的文件名将会使未经排序的:

cd ~
ls /bin /usr/bin

此时, 如果使用sort并将其放入管道

cd ~
ls /bin /usr/bin | sort

我们将得到经过排序后的文件名.

 

PS: 由于uniq命令需要接收有序数据, 因此通常sort与uniq会结合使用:

cd ~
ls /bin /usr/bin | sort | uniq

 

wc

wc命令源于word count的单词首字母, 其意为字数统计, 但实际上wc能做的远不止如此.

拿上一章所创建的文件举例, 如果我们要统计output.txt文件中的字符数据, 可以这样使用:

wc output.txt

此时, wc命令所输出的内容包括3组使用空格分割的数字以及目标文件名, 它们分别代表 行数 单词数 字节数.

同样的, 如果我们不为wc指定输入, 那么它将从标准输入(键盘)中获取数据.

如果我们只希望统计数据中的行数, 那么可以使用-l参数

cd ~
ls /bin /usr/bin | sort | uniq | wc -l

这样, 我们就得到了bin和usr/bin目录下所有的非重复文件(文件夹)计数.

 

head 和 tail

有时我们并不需要查看一个命令的所有输出, 可能我们只想要前几行或末尾几行的内容, 这时就可以使用head和tail命令;

在默认情况下, head会打印前10行数据, tail则会打印末尾10行数据. 并且它们提供了一个"-n"参数以供显式指定打印的行数;

它们同样可以被用在管道线中:

head -n 15 output.txt | grep a

这样, 我们会获得output.txt的前15行中带有字符"a"的行.

 

此外, tail命令还提供了"-f"参数以供我们选择是否实时更新内容, 如果在调用时使用-f参数, 那么每当目标更新, tail就将立刻反映到输出上. 这在查看日志文件时比较常用:

tail -f /var/log/messages

 

tee

如果在管道线的其中某一步我们希望取得当前步骤的输入\输出时, Shell为我们提供了tee命令, 它会从标准输入中取得数据, 并将其复制到标准输出.

文字上可能难以描述tee所存在的意义, 但代码可以:

ls ~ | tee home_ls.txt | grep pdf

通过执行上述代码, 我们将得到一个home_ls.txt文件夹, 内容为home目录下所有文件(ls的执行结果), 并且, 我们会在终端上得到home目录下所有文件名带有"pdf"的文件.

通过上面的例子不难认识到, tee的存在使管道线执行过程中数据的I/O操作成为了可能, 相信在今后的使用中也会逐渐认识到它的作用.

上一篇:sort和uniq


下一篇:Unix管道之美