文件上的 diff3 没有发现差异:
$ grep -P '\[\[.*?\]\]' -o intro.tex | sort > A.txt
$ grep -P '\[\[.*?\]\]' -o intro.tex | sort | uniq > B.txt
$ grep '\\pnum %% \[\[' intro.tex | sed 's/\\pnum %% //' | sort > C.txt
$ diff3 A.txt B.txt C.txt | wc -l
0
diff3 在运行相同命令的进程替换上发现了差异:
$ diff3 \
<(grep -P '\[\[.*?\]\]' -o intro.tex | sort) \
<(grep -P '\[\[.*?\]\]' -o intro.tex | sort | uniq) \
<(grep '\\pnum %% \[\[' intro.tex | sed 's/\\pnum %% //' | sort) | wc -l
95
为什么?有任何想法吗?
最小复制器:
$ echo test > a
$ diff3 a a a
$ diff3 <(cat a) <(cat a) <(cat a)
====1
1:1c
test
2:0a
3:0a
如果我们运行
diff3
在strace -f
:如您所见,
diff3
调用了diff
两次,第三个文件是两次调用的操作数之一。使用 ksh 样式的
<(...)
进程替换,文件是一个管道。是相同的:
除了使用 0 以外的 fd。
因此,对于 的第三个参数
diff3
,第一个diff
将消耗整个输入,第二个将没有任何内容可读,因此文件将显示为空。所以第三个参数至少不能是管道¹。
如果使用
zsh
,您可以使用=(...)
使用临时文件而不是管道的进程替换形式:(前两个仍然可以是管道)。
在你的情况下:
(我还删除了多余的
grep
和并在非选项之前uniq
移动了选项)。-o
你甚至可以做一些因式分解:
¹ 如果第三个参数
-
解释diff3
为读取标准输入,那么第二个参数不能是管道,因为在这种情况下它是传递给两个调用的那个diff
。您会注意到手册上说:“这三个文件名中最多有一个可能是-
,它告诉diff3
您读取该文件的标准输入。”