Linux <(...) 进程替换
参考资料
- shell 里的进程替换(Process Substitution)
- 23 shell 进程替换
目录
- 一. 简介
- 二. 用法示例
- 2.1 `diff` 和 `comm` 比较两个命令的输出
- 2.2 `paste` 合并多个命令的输出
- 2.3 `sort` 对多个数据源排序
- 2.4 `awk` 处理多个输入
- 2.5 `split` 进行文件拆分
一. 简介
在 Linux Shell(主要是 Bash
和Zsh
)中,进程替换(Process Substitution) 允许将命令的输出当作文件一样使用,常见的用法有:
>(...)
<(...)
⏹基本语法
- 进程替换
<(...)
允许你把一个命令的输出当作文件使用,而不是使用管道|
command <(other_command)
⏹作用
- 把命令的输出当成临时文件供另一个命令读取。
- 适用于需要文件参数的命令,而不能直接用管道的情况。
💥注意事项:
- 进程替换的
<(...)
产生的是一个临时文件,某些不支持文件描述符的命令可能无法直接使用。 - 在某些精简版的 Shell(如
sh
)中不支持进程替换。
二. 用法示例
2.1 diff
和 comm
比较两个命令的输出
⏹diff命令
- 把
<(ls dir1)
当做一个临时文件 - 把
<(ls dir2)
当做另一个临时文件
diff <(ls dir1) <(ls dir2)
⇓⇓⇓等价于下面这种比较方式⇓⇓⇓
ls dir1 > temp1
ls dir2 > temp2
diff temp1 temp2
rm temp1 temp2
⏹comm命令
apluser@ubuntu24-01:~$ comm <(seq 5) <(seq 2)
1
2
3
4
5
2.2 paste
合并多个命令的输出
apluser@ubuntu24-01:~$ paste <(seq 3) <(echo -e "A\nB\nC")
1 A
2 B
3 C
apluser@ubuntu24-01:~$ paste <(wc -l < /etc/passwd) <(wc -l < /etc/group)
34 59
apluser@ubuntu24-01:~$ paste <(wc -l /etc/passwd) <(wc -l /etc/group)
34 /etc/passwd 59 /etc/group
2.3 sort
对多个数据源排序
apluser@ubuntu24-01:~$ sort <(echo -e "3\n1\n2") <(echo -e "9\n7\n8")
1
2
3
7
8
9
2.4 awk
处理多个输入
- awk 读取两个命令的输出,并打印对应的文件路径和内容
FILENAME
指向/dev/fd/...
,代表进程替换的临时文件。
apluser@ubuntu24-01:~$ awk '{print FILENAME, $0}' <(echo "hello") <(echo "world")
/dev/fd/63 hello
/dev/fd/62 world
为了能够在不同进程之间传递数据,实际上进程替换会跟系统中的文件关联起来,这个文件的名字为/dev/fd/n
(n 是一个整数)。
该文件会作为参数传递给()
中的命令,()
中的命令对该文件是读取还是写入取决于进程替换格式是 <
还是 >
:
- 如果是
>()
,那么该文件会给()中的命令提供输入;借助输出重定向,要输入的内容可以从其它命令而来。 - 如果是
<()
,那么该文件会接收()中命令的输出结果;借助输入重定向,可以将该文件的内容作为其它命令的输入。
2.5 split
进行文件拆分
我们在这篇 Linux paste命令 文章使用使用了如下命令进行文件拆分,其中-
表示标准输入流,也就是grep命令的执行结果。
grep "SEQIN" system_info.log | grep -o -e "^\S*" -e "isuuePayId=\S*" -e "jmw_state=\S*" | \
split -l 3 - part_ --numeric-suffixes=0 --additional-suffix=.log
我们也完全可以通过进程替换的方式来实现上述命令
split -l 3 <(grep "SEQIN" system_info.log | grep -o -e "^\S*" -e "isuuePayId=\S*" -e "jmw_state=\S*") part_ \
--numeric-suffixes=0 --additional-suffix=.log
⏹⇓⇓⇓实现效果如下⇓⇓⇓