我想要一个可以在任意 bash 流上使用的差异包装器,它只打印差异直到最短的行长。这对于常规文件很容易,只需阅读两次即可:
~/bin/mindiff:
min=$(calc -p 'min(' $(wc -l < "$1") ', ' $(wc -l < "$2") ')')
diff <(head -$min "$1") <(head -$min "$2")
(我发现这对于检查运行时文本处理输出的差异非常有用。)
注意:我不希望逐行进行差异。我想要上面的脚本做什么(它允许跨越多行的差异),但是在流上工作。我只是不希望由于一个流/文件比另一个长而导致底部混乱。我更喜欢调用常规差异,以便我可以传递任何常规差异选项,如 -B1、-y --suppress-common-lines -W180、-U1 管道到 dwdiff 以获取带有颜色的花哨的单词差异等。
但是,我希望能够在任意流上调用它,只读取一次,例如
mindiff <(sed 's/fluff//' /tmp/out) <(ssh server sed 's/fluff//' /tmp/out)
在一些#bash 向导的帮助下,我得到了这个 awk 助手,它并行读取两个流直到一个结束,然后运行 diff:
mkfifo a b
awk '
BEGIN{ f2=ARGV[2];ARGC-- }
( (getline line <f2)>0 ) { print > "a"; print line > "b" }
' "$1" "$2" &
diff a b
它适用于短玩具示例,但如果我尝试类似
mindiff <(yes |head -40000) <(yes |head -40000)
它只是挂起。添加“打印NR;” 到 awk 显示它上升到第 36865 行(而<(yes yesyes)
它上升到 10533,所以它似乎允许一定数量的字节,而不管行数如何)。
添加system("")
到 flush awk 每一行使它更早停止(第 34818 行)。
是什么阻止了我的差异?
更新:我的怀疑是,在diff a b
a 和 b 很大的地方运行时,diff 会要求 a 中的一堆行,然后是 b 中的一堆。由于辅助脚本只提供并行行,它尝试将一行推送到 a,然后将另一行推送到 b,但 diff 正在从 a 请求更多行,因此推送到 b 挂起。但是,在执行常规diff <(cmd) <(cmd)
操作时,第一个 cmd 可以推送一堆行,而第二个则等待。