在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操作成为了可能, 相信在今后的使用中也会逐渐认识到它的作用.