Linux Shell Pipeline
Linux管道符的知识点和使用
先记住一句话核心: 管道符号
|,作用是:把左边命令打印出来的内容,直接交给右边命令去处理。 Linux 一切皆文本,管道就是文本传送带,把前一个工具的结果,传给下一个工具。
1. 管道的底层原理
1.1 三大输出流
Linux 每个命令运行时,都有 3 个数据流:
-
标准输入 stdin:命令读取的内容(好比人的耳朵,接收数据)
-
标准输出 stdout:命令正常打印的内容(好比嘴巴,输出内容)
-
标准错误 stderr:命令报错的红色错误信息
1.2 管道规则
- 只转发 标准输出 (stdout)
- 默认不转发 错误信息 (stderr)
- 格式固定:
命令1 | 命令2 | 命令3数据流向: 命令 1 打印的内容 → 自动变成 命令 2 的输入 → 命令 2 处理完 → 传给命令 3
2. 基础示例
2.1 示例一
ls -la | grep "txt"-
ls -la:列出当前文件夹所有文件 + 详细信息(这是左边输出) -
|:把上面列出的所有内容,传给右边 -
grep "txt":筛选出包含 txt 字符串的行
2.2 示例二
ps aux | grep python | wc -l-
ps aux:列出系统所有正在运行的进程 -
第一层
|:全部进程信息传给 grep -
grep python:只筛选出和 python 相关的进程 -
第二层
|:筛选后的内容传给 wc -
wc -l:统计行数(也就是统计 python 进程数量)
3. 进阶:文本流水线
3.1 错误日志筛选 + 去重
cat /var/log/syslog | grep "ERROR" | sort | uniq分步拆解:
-
cat /var/log/syslog:读取系统日志文件全部内容 -
grep "ERROR":只保留包含 ERROR 的错误日志 -
sort:把日志内容按字母 / 时间排序 -
uniq:去掉完全重复的日志行
3.2 统计每种错误出现次数
cat /var/log/syslog | grep "ERROR" | sort | uniq -c | sort -nr新增参数解释:
-
uniq -c:去重 + 在每行前面加上出现次数 -
sort -nr:-
-n:按数字排序 -
-r:倒序(错误最多的排最上面)
-
4. 管道 + xargs
4.1 为什么需要 xargs?
-
管道
|传递的是内容(文本),当做「输入」 -
很多命令(rm、mkdir、curl)不接收文本输入,只接收「参数」
-
xargs 作用:把管道传过来的文本,转换成 命令的参数
4.2 示例
4.2.1 删除所有 .log 文件
find . -name "*.log" | xargs rm拆解:
-
find . -name "*.log":找出当前目录下所有后缀为.log的文件,打印出来 -
xargs rm:把上面找到的文件名,一个个当成rm的参数 等价于:rm 日志1.log 日志2.log ...
4.2.2 批量访问网址
cat urls.txt | xargs -P 4 -I {} curl -s {}参数:
-
-P 4:同时开 4 个进程,并行执行 -
-I {}:用{}代替每一行内容 -
curl -s {}:静默访问每一个网址
5. 进程替换 <() 命令
5.1 核心作用
有些命令不支持管道,就用 < 把命令输出伪装成临时文件
diff <(cat file1.txt) <(cat file2.txt)diff:对比两个文件差异<(cat file1.txt):把 file1 内容,假装成一个文件
*等价写法(管道版):
cat file1.txt | diff - <(cat file2.txt)这里的 - 代表:读取管道传来的stdout的内容
5.2 进程替换与文件重定向
| 方式 | 语法 | 本质 | 使用场景 |
|---|---|---|---|
| 进程替换 | cat <(cmd) | 将命令输出作为文件路径传入 | 需要文件名参数时 |
| 输入重定向 | cat < file 或 cmd < file | 将文件内容作为stdin | 从文件读取输入 |
- 进程替换
<(...)
# 将命令输出伪装成文件,传给需要文件参数的命令cat <(echo "hello world")# 等价于: cat /dev/fd/63 (bash创建的临时管道文件描述符)
# 实际应用:对比两个命令输出diff <(ls dir1) <(ls dir2)
# 写入文件(通过 cat 中转)cat <(echo "content") > output.txt原理:Bash 创建命名管道(FIFO)或
/dev/fd文件,让cat以为是普通文件。
- 输入重定向
<
# 从文件读取,写入另一个文件(相当于复制)cat < input.txt > output.txt
# 等价于cat input.txt > output.txt
# 结合 Here Documentcat << 'EOF' > output.txtline 1line 2EOF6. 标准错误管道处理
6.1 默认问题
管道只传正常输出,报错信息会直接打印屏幕,不走管道。
6.2 两个核心数字
-
1= 标准输出(正常内容) -
2= 标准错误(报错内容)
6.3 示例
6.3.1 屏蔽错误
find /root 2>/dev/null | grep "file"-
2>/dev/null:把错误信息丢进null设备,直接删除 -
只有正常搜索结果进入管道被 grep 筛选
6.3.2 错误也走管道
find /root 2>&1 | grep "Permission"-
2>&1:把 错误流 (2) 合并到 正常输出流 (1) -
此时正常内容 + 报错内容全部进入管道,可以筛选权限报错
7. 三通阀(tee命令)
7.1 作用
一份数据两用:
-
屏幕上正常显示
-
同时保存到文件
7.2 基础用法
cat file.txt | tee backup.txt | grep "keyword"流程:
-
读取 file.txt
-
tee backup.txt:-
复制一份内容存入
backup.txt -
同时把内容继续往后传给管道
-
-
最后 grep 筛选关键词
7.3 追加写入
echo "新内容" | tee -a log.txt-a:append 追加,不会删掉文件原有内容
8. 流式编辑器(sed命令)
这个可以修改前端管道的内容,然后传递给后端的管道,比如
cmd_1 | sed [opts] 'cmd' | cmd_2
8.1 基础用法
sed [opts] 'cmd' 文件sed [opts] -e 'cmd_1' -e 'cmd_2' 文件- 基础示例 (将每行第一个匹配的
foo替换为bar)
sed 's/foo/bar/' file- ori
foo is greatanother foo here foono match herefoofoo test- dest
bar is greatanother bar here foono match herebarfoo test8.2 核心命令
8.2.1 替换(s)
# 基本替换:每行第一个匹配sed 's/foo/bar/' file
# 全局替换(g):每行所有匹配sed 's/foo/bar/g' file
# 替换第 N 个匹配sed 's/foo/bar/2' file # 替换每行第 2 个sed 's/foo/bar/2g' file # 从第 2 个开始,替换后面所有
# 使用分隔符(当替换路径等含/的内容时)sed 's#/usr/local#/opt#g' file # 用 # 代替 /sed 's|/home/user|/data|g' file # 用 | 代替 /8.2.2 删除(d)
# 删除指定行sed '3d' file # 删除第 3 行sed '1,5d' file # 删除 1-5 行sed '$d' file # 删除最后一行
# 删除匹配行sed '/pattern/d' file # 删除含 pattern 的行sed '/^#/d' file # 删除注释行(以#开头)sed '/^$/d' file # 删除空行8.2.3 打印(p)与静默(-n)
# 默认 sed 会打印所有行,p 会额外打印匹配行(导致重复)sed '/pattern/p' file # 匹配行出现两次
# -n 静默模式,只打印指定内容sed -n '/pattern/p' file # 只打印匹配行sed -n '5,10p' file # 打印 5-10 行(类似 head/tail)sed -n '1~2p' file # 打印奇数行(从1开始,步长2)8.2.4 插入、追加、修改(i/a/c)
# i:行前插入sed '3i\This is new line' file
# a:行后追加sed '3a\This is new line' file
# c:替换整行sed '3c\Replace line 3' file
# 匹配后操作sed '/pattern/a\New line after match' file8.3 常用选项
| 选项 | 作用 |
|---|---|
-i | 原地修改文件(in-place) |
-i.bak | 原地修改并备份原文件为 .bak |
-n | 静默模式,配合 p 使用 |
-e | 多命令连接 |
-r | 使用扩展正则(ERE),免转义 |
-E | 同 -r(BSD/macOS 风格) |
8.4 实用组合示例
# 1. 原地修改文件(危险操作,建议先备份)sed -i 's/localhost/127.0.0.1/g' config.conf
# 2. 删除文件中的 Windows 换行符 (^M)sed -i 's/\r$//' file.txt
# 3. 提取特定行范围到另一个文件sed -n '100,200p' log.txt > extracted.txt
# 4. 多命令组合sed -e 's/foo/bar/g' -e 's/hello/hi/g' file
# 5. 从管道读取(无输入文件)cat file | sed 's/foo/bar/g'# 更优写法(避免无用猫)sed 's/foo/bar/g' < file
# 6. 复杂:删除空行和注释,提取有效配置sed '/^#/d; /^$/d' config.ini
# 7. 使用扩展正则(更简洁)sed -r 's/(foo|bar)/baz/g' file # 无需转义 ()8.5 注意事项
| 注意点 | 说明 |
|---|---|
-i 无备份风险 | sed -i 直接修改,建议先用 sed '' file 测试 |
| 正则转义 | 基础正则中 ()+?{} 需转义,用 -r 可免转义 |
| macOS 差异 | BSD sed 要求 sed -i '' 's///' file(必须给备份后缀) |
| 单引号优先 | 避免 shell 提前展开变量,需要变量时用双引号 |
9. 匿名管道 和 命名管道
9.1 匿名管道 |
-
临时生效,命令结束就消失
-
只能一条命令行里多个命令连用
9.2 命名管道 FIFO (好玩)
可以跨两个终端、跨进程传数据
# 1. 创建一个管道文件mkfifo mypipe
# 2. 第一个终端:往管道写数据(后台运行 &)echo "测试数据" > mypipe &
# 3. 第二个终端:读取管道数据cat < mypipe10. 实用指令组合
- 看文件最后 100 行 + 实时过滤错误
tail -f 日志文件.log | grep error- 统计当前目录所有文件后缀数量
find . -type f | sed 's/.*\.//' | sort | uniq -c- 查看目录内容并分页
ls -la | less11. 结尾
没了喵,谢谢欣赏

文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!