两个大文件的区别


14

我有“ test1.csv”,它包含

200,400,600,800
100,300,500,700
50,25,125,310

和test2.csv,其中包含

100,4,2,1,7
200,400,600,800
21,22,23,24,25
50,25,125,310
50,25,700,5

现在

diff test2.csv test1.csv > result.csv

与...不同

diff test1.csv test2.csv > result.csv

我不知道哪个是正确的顺序,但是我想要其他东西,上面的两个命令都将输出类似

2 > 100,4,2,1,7
   3 2,3c3,5
   4 < 100,300,500,700
   5 < 50,25,125,310
   6 \ No newline at end of file
   7 ---
   8 > 21,22,23,24,25
   9 > 50,25,125,310

我只想输出差异,因此results.csv应该看起来像这样

100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5

我试过了diff -qdiff -s但他们没有成功。顺序无关紧要,重要的是我只希望看到区别,没有>或<也没有空格。

grep -FvF 对较小的文件而不是较大的文件做了the俩

第一个文件包含500万行,第二个文件包含1300行。

所以result.csv应该导致〜4,998,700行

我也试过了grep -F -x -v -f ,那没用。



1
@Tim我看到了您的链接,并且我是一个老会员,所以我知道规则,但是很粗心,对不起:)正在编辑它,我看到一个弹出窗口,指出帖子已被编辑,所以您为我做了工作,谢谢先生
Lynob 2015年

50,25,125,310是常见的两种file..you需要从你期望的输出删除..
heemayl

应该保留订单吗?
kos 2015年

1
某种程度上取决于您要处理的信息,diff,IMO,是用来制作补丁的。无论如何,我现在确定您最好的工具diff,grep,awk或perl。

Answers:


20

听起来像是工作comm

$ comm -3 <(sort test1.csv) <(sort test2.csv)
100,300,500,700
    100,4,2,1,7
    21,22,23,24,25
    50,25,700,5

如中所述man comm

   -1     suppress column 1 (lines unique to FILE1)

   -2     suppress column 2 (lines unique to FILE2)

   -3     suppress column 3 (lines that appear in both files)

因此,这-3意味着将仅打印文件之一唯一的行。但是,这些缩进将根据在其中找到的文件来缩进。要删除选项卡,请使用:

$ comm -3 <(sort test1.csv) <(sort test2.csv) | tr -d '\t'
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5

在这种情况下,您甚至不需要排序文件,并且可以将以上内容简化为:

comm -3 test1.csv test2.csv | tr -d '\t' > difference.csv

您还没被200,[...]行后的空格所迷惑吗?:)
kos 2015年

@kos不,我先从文件中删除了尾随空格。我假设OP的文件实际上没有它们。
terdon 2015年

6

使用grepbash流程替换:

$ cat <(grep -vFf test2.csv test1.csv) <(grep -vFf test1.csv test2.csv)
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5

将输出另存为results.csv

cat <(grep -vFf test2.csv test1.csv) <(grep -vFf test1.csv test2.csv) >results.csv
  • <()bash流程替代模式

  • grep -vFf test2.csv test1.csv 会发现只有 test1.csv

  • grep -vFf test1.csv test2.csv 会发现只有 test2.csv

  • 最后,我们对结果进行总结 cat

或者按照Oli的建议,也可以使用命令分组:

$ { grep -vFf test2.csv test1.csv; grep -vFf test1.csv test2.csv; }
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5

或者只是一个接一个地运行,因为它们都在向STDOUT写入数据,因此最终会被添加:

$ grep -vFf test2.csv test1.csv; grep -vFf test1.csv test2.csv
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5

1
为什么要使用cat两个重定向命令?为什么不跑一个然后跑另一个呢?grep ... ; grep ...或者{ grep ... ; grep ... ; }如果您想对集体输出做点事情。
奥利(Oli)

@Oli谢谢..那是一个好主意..我没有想到..
heemayl 2015年

4

如果行顺序不相关,请使用awkperl

awk '{seen[$0]++} END {for (i in seen) {if (seen[i] == 1) {print i}}}' 1.csv 2.csv

使用grep以获得公共线和过滤那些出:

grep -hxvFf <(grep -Fxf 1.csv 2.csv) 1.csv 2.csv

内部grep获取公共行,然后外部grep查找与这些公共行不匹配的行。


您的awk命令只是重新实现sort | uniq -u,当一个文件包含重复的行时,它会给出错误的答案。对于grep,我会说“内部” /“外部”,而不是“内部” /“外部”。
彼得·科德斯

@PeterCordes是的,确实如此,您是谁呢?这是错误的结果?
muru

在那个极端的情况下,这并不是问题的确切含义,这是错误的。可能是有人想要的,但是您应该指出您awk要打印的内容comm -3diff答案将要打印的内容之间的区别。
Peter Cordes

再次@PeterCordes,你要说谁?在OP表示他们想要的是之前,我不在乎输出是否与的不同comm -3。我看不出有任何理由为什么应该解释。如果要编辑便笺,请放心。
muru

OP表示他希望有所作为。这并不总是您的程序产生的。对于一个测试用例产生相同输出,但不满足所有情况下编写的描述的程序,需要警惕。我在这里这么说,无论我是谁还是你是谁,都是如此。我加了一条纸条。
彼得·科德斯

4

使用 --*-line-format=...选项diff

您可以diff准确地说出所需内容-如下所述:

diff --old-line-format='%L' --new-line-format='%L' --unchanged-line-format='' f1.txt f2.txt

可以非常详细地指定diff的输出,类似于 printf数字格式。

第一个文件test1.csv中的行称为“旧”行,第二个文件中的行称为test2.csv“新”行。那在什么时候有意义diff用于查看文件中的更改。

我们需要的选项是设置“旧”行,“新”行和“未更改”行的格式的选项。
我们需要的格式非常简单:
对于更改的行(新的和旧的),我们只希望输出行的文本。%L是行文本的格式符号。
对于未更改的行,我们什么也不想显示。

这样,我们可以--old-line-format='%L'使用示例数据编写类似的选项,并将其放在一起:

$ diff --old-line-format='%L' --new-line-format='%L' --unchanged-line-format='' test1.csv test2.csv
100,4,2,1,7
100,300,500,700
21,22,23,24,25
50,25,700,5


性能说明

由于文件大小不同,请不要紧交换输入文件,这可能是因为文件的内部工作原理 diff可以比另一种更好。更好的是需要更少的内存或更少的计算。

有一个用于diff处理大文件的优化选项:--speed-large-files。它使用有关文件结构的假设,因此尚不清楚它是否对您有帮助,但值得尝试。

格式选项在所述man diff--LTYPE-line-format=LFMT


3

由于不需要保留订单,因此只需:

sort test1.csv test2.csv | uniq -u
  • sort test1.csv test2.csv:合并和排序,test1.csv以及test2.csv
  • uniq -u:仅打印没有重复的行

如果一个文件两次包含一行,而另一行中没有出现该行,则该方法不起作用。两种情况都会有diff结果。
Volker Siegel
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.