我想要一个diff包装器,我可以在任意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用dhdiff传递给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("")
以刷新每行的awk使其更早停止
(第34818行)。
什么阻挡了我的差异?
更新:我的怀疑是,在运行diff a b
a和b很大的情况下,差异会从a请求一堆行,然后从b请求一堆行。由于辅助脚本只提供并行行,因此它会尝试将一行推送到a,然后将一行推送到b,但是diff正在请求a中的更多行,因此push to b会挂起。然而,当执行常规diff <(cmd) <(cmd)
时,第一个cmd可以推送一堆行,而第二个等待。
答案 0 :(得分:1)
根据您的澄清改变答案。
我建议您转储awk
并使用perl
脚本作为帮助来完成这项工作。
#!/usr/bin/perl
use strict;
use warnings;
my ($f1 ,$f2)=@ARGV;
open(my $fifo1, '<', $f1) || die("Couldn't open file $f1: $!");
open(my $fifo2, '<', $f2) || die("Couldn't open file $f2: $!");
my $count=0;
while(not (eof($fifo1) or eof($fifo2)) ) {
my $a = <$fifo1>; chomp($a);
my $b = <$fifo2>; chomp($b);
print "my_diffing_function(\'$a\', \'$b\')\n";
# Alternatively write these lines to 2 fifos
++$count;
}
close $fifo1;
close $fifo2;
这允许您定义自己的diff函数以逐行检查是否存在差异。或者你可以使用Text::Diff来做同样的事情。更好的是,您可以打开2个FIFO来写入并让diff
处理这些FIFO。
要测试它,只需执行:
samveen@precise:/tmp$ perl differ.pl <(yes |head -n 20) <(yes 'n' |head -n 30)
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
my_diffing_function('y', 'n')
你可以打开一对管道来输出这个助手脚本并写出来,然后在管道的一侧产生差异。
答案 1 :(得分:0)
另一种选择是简单地解析diff输出并去除底部的绒毛。不幸的是,这似乎是最简单的。例如。处理-u和常规diff输出:
diff "$@" "$if1" "$if2" | awk '
lines && /^@@ -[0-9]*,[0-9]* \+[0-9]*,[0-9]* @@$/ {print lines; lines=""}
lines && /^[0-9]+,[0-9]+d[0-9]+$/ {print lines; lines=""}
// {if(lines)lines=lines"\n"$0; else lines=$0}
'
处理-y需要更多的工作。这不是一个非常令人满意的解决方案。