pipeline的语法是: command | comand
process substitution的语法是:
- >(command list)
- <(command list)
我们对pipe非常熟悉了,pipe把上一个命令的STDOUT,连接到下一个命令的STDIN
比如,把date的STDOUT连接到cat的STDIN上,cat从STDIN读取内容,输出date的值
# date|cat Fri Oct 22 15:27:25 CST 2021
pipe用于处理多个命令顺序执行是极好的,但有些场景下,需要多个输入的时候,pipe就不够用了,需要使用Process substitution,Process substitution的基本用途也是实现重定向,但和pipe有区别
假设有两个文件:
# cat a e d c b a x
# cat b g f e d c b
我需要用comm命令比较两个文件中的不同的部分,comm命令要求文件要预先排序。
常规做法可能是一个个先排序,然后再comm:
sort a|uniq > tmp1 sort b|uniq > tmp2 comm tmp1 tmp2
如果我们想一条指令就搞定这三个步骤的话,pipe是做不到的,process substitution就可以
comm -3 <(sort a|uniq) <(sort b|uniq)
Process substitution
process substitution的语法,是>(command list)和<(command list)
<(command list)的意思,是把小括号内command list的STDOUT,映射到一个fd,外部程序通过这个fd,可以读取command list的STDOUT内容。
同理>(command list)代表着把command list的STDIN,映射到一个fd,向该fd写入内容,会传递到command list的STDIN
比如:
# echo <(date) /dev/fd/63
能清楚的看到<(date)代表着/dev/fd/63这个fd。echo指令并不会主动从fd读取内容,但是有些指令,比如cat,假如给了一个fd, 它就会主动读取fd的内容:
# cat <(date) Fri Oct 22 16:38:04 CST 2021
可以看到cat从<(date)代表的fd中读取到了真正的时间数据。
Process substitution在某些场景特别有用,比如上面所说,某些命令需要设置多个输入。
还有一种场景,比如需要向某个命令传递数据,但该命令的STDIN已经被占用了,使用pipeline无法向其传递数据,因为pipeline只能传递给STDIN,此时就可以通过Process substitution传递一个fd,通过fd读取数据,当然,前提是该命令具备从多个fd获取数据的能力
Process substitution可以代替pipe的作用,以下二者效果是相同的:
command3 < <(command1; command2) (command1; command2) | command3
注意这里出现了两个<, 第二个<(command1; command2)代表着Process substitution, 是一个 fd。第一个<就是我们常见的重定向符号,command3 < <(command1; command2)就相当于:
command3 < fd
意思是把fd重定向到command3的标准输入STDIN。多加了这个重定向符号,就和pipeline一样了,把Process substitution的fd,连接到了command3的STDIN
对比一下,这是把fd,直接传递给cat,cat从fd直接读取数据
cat < (date) equal to: cat fd
这是把fd连接到cat的STDIN, cat从STDIN读取数据:
cat < <(date) equal to: cat STDIN---connect to-->fd
最后来个反向例子:
# date > >(cat) Fri Oct 22 17:04:50 CST 2021
发表回复