Linux 管道工作原理与使用
管道(|)是 Linux 命令行里超级好用的工具,它能让命令像流水线一样协作,把一个命令的输出直接传给另一个命令当输入。
基于 stdin、stdout 和 stderr 的知识,管道主要处理 stdout 和 stdin,让你轻松组合命令来完成复杂任务。
1. 什么是管道?
管道用 | 符号表示,它的作用是把左边命令的 stdout 直接送给右边命令的 stdin。简单说,就是让命令“串联”起来,像接水管一样,数据从一个命令流到下一个。
比如:
ls | grep "txt"
这里:
ls的 stdout(当前目录的文件列表)通过管道传给grep。grep "txt"从 stdin 读取数据,过滤出包含 “txt” 的行。
结果是只显示文件名中包含 “txt” 的文件。
2. 管道的工作原理
管道的核心是把 stdout 和 stdin 连接起来。Linux 会:
- 运行左边的命令,把它的 stdout 临时存到一个内存缓冲区。
- 把这个缓冲区的内容作为右边命令的 stdin。
- 右边命令处理输入,输出结果(通常是 stdout,显示在终端)。
重要提醒:
- 管道只传 stdout,不传 stderr。stderr 默认还是显示在终端。
- 管道是单向的,数据从左到右流动。
试试这个:
ls /etc /notexist | grep "conf"
ls /etc /notexist会输出/etc的文件列表(stdout),同时在终端显示错误(stderr:ls: cannot access '/notexist': No such file or directory)。grep "conf"只从 stdin(即/etc的文件列表)过滤出包含 “conf” 的行。
3. 基本用法:单个管道
单个管道是最简单的用法,把两个命令连起来:
echo "apple banana cherry" | tr 'a' 'A'
echo输出 “apple banana cherry” 到 stdout。tr 'a' 'A'从 stdin 读取,把小写a替换成大写A。
结果是:
Apple bAnAnA cherry
另一个例子:
cat file.txt | sort
如果 file.txt 包含几行文本,cat 把内容送到 stdout,sort 从 stdin 读取并按字母顺序排序后输出。
4. 多管道:串联多个命令
管道可以无限串联,组成复杂的处理链。比如:
ls /etc | grep "conf" | sort | head -n 2
这行命令:
ls /etc列出/etc目录的内容。grep "conf"过滤出包含 “conf” 的行。sort按字母顺序排序。head -n 2只取前两行。
每个命令的 stdout 都成为下一个命令的 stdin,层层处理。
5. 管道与重定向结合
管道和重定向可以一起用,灵活处理输入输出。比如:
ls /etc | grep "conf" > output.txt
ls /etc | grep "conf":管道过滤出包含 “conf” 的文件。> output.txt:把grep的 stdout 写入output.txt。
再来个复杂点的:
cat input.txt | grep "error" > output.txt 2> error.log
cat input.txt的 stdout 送到grep。grep "error"过滤出包含 “error” 的行,输出到 stdout。> output.txt把grep的 stdout 存到output.txt。2> error.log把grep的 stderr(如果有)存到error.log。
6. 处理 stderr 在管道中
管道默认只传 stdout,stderr 不会进入管道。如果想让 stderr 也参与管道,需要先把 stderr 重定向到 stdout。用 2>&1:
ls /etc /notexist 2>&1 | grep "conf"
2>&1把 stderr 合并到 stdout。- 合并后的输出(stdout + stderr)通过管道送到
grep。 grep "conf"过滤包含 “conf” 的行(可能包括错误信息)。
试试看,输出可能包含错误信息(如果错误信息里带 “conf”)。
7. 使用 tee:在管道中保存中间结果
有时候你想在管道处理的同时,把中间结果存到文件,这可以用 tee 命令。tee 从 stdin 读取数据,同时写到文件和 stdout。
比如:
ls /etc | grep "conf" | tee conf_files.txt | sort
ls /etc | grep "conf":过滤出包含 “conf” 的文件。tee conf_files.txt:把grep的输出存到conf_files.txt,同时继续传给下一个命令。sort:对结果排序。
运行后,conf_files.txt 存了 grep 的输出,终端显示排序后的结果。
8. 常见管道命令组合
以下是一些超实用的管道组合:
- 统计行数:
cat file.txt | wc -l
wc -l 从 stdin 读取,统计行数。
- 查找并排序唯一项:
cat file.txt | sort | uniq
sort 排序,uniq 删除重复行。
- 过滤并计数:
dmesg | grep "error" | wc -l
统计内核日志(dmesg)中包含 “error” 的行数。