通过命令管道后的差异标准输入

Aar*_*sen 6 shell pipe

我想要以下形式的东西(填空):

cmd1 | ____ cmd2 ____
Run Code Online (Sandbox Code Playgroud)

这与此等效,但不写入任何文件:

cmd1 > temp
cmd2 < temp | diff temp -
Run Code Online (Sandbox Code Playgroud)

cmd1 实际上不是命令,它是来自文本编辑器的 stdin 流,因此不能多次运行,因此这不起作用:

diff <(cmd1) <(cmd1 | cmd2)
Run Code Online (Sandbox Code Playgroud)

但这基本上是我想要的。

我使用的是 macOS,但我更喜欢它与 linux 兼容。

mik*_*mik 6

一般来说,当你不想写文件时,可以用(命名)管道来替换它,但管道不能同时被两个进程读取。在您的情况下,您可以使用tee拆分输入并为其一端使用命名管道:

mkfifo p
cmd1 | tee p | cmd2 | diff p -
rm p
Run Code Online (Sandbox Code Playgroud)

然而,这有一个主要缺点:管道的缓冲区有限(Linux 上为 64k),因此当 diff 读取其中一个管道与另一个管道进行过多比较时,整个管道将陷入僵局。可以使用buffer至少一个管道的命令来规避该问题:

mkfifo p
cmd1 | tee p | cmd2 | buffer | diff p -
rm p
Run Code Online (Sandbox Code Playgroud)

另请参阅此处了解其他缓冲选项。

死锁的另一个解决方案是使用变量来缓冲cmd1其中的整个输出(将其加载到内存中):

cmd1 | ( b=$(cat); cmd2 <<<"$b" | diff <(echo "$b") - )
Run Code Online (Sandbox Code Playgroud)