两个大文件的差异

两个大文件的差异

我有“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对较小的文件有效,对大文件无效

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

因此 results.csv 应该有 ~4,998,700 行

我也尝试过,grep -F -x -v -f 但没有效果。

答案1

听起来像是这样的工作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

答案2

使用过程替换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

或者奥利建议,您还可以使用命令分组:

$ { 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

答案3

如果行的顺序不相关,则使用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 查找与这些公共行不匹配的行。

答案4

由于不需要保留顺序,因此只需:

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

相关内容