如何显示共同的线(反向差异)?


170

我有一系列文本文件,我想了解它们的共同点,而不是彼此之间不同的地方。命令行unix或Windows都可以。

foo:

linux-vdso.so.1 =>  (0x00007fffccffe000)
libvlc.so.2 => /usr/lib/libvlc.so.2 (0x00007f0dc4b0b000)
libvlccore.so.0 => /usr/lib/libvlccore.so.0 (0x00007f0dc483f000)
libc.so.6 => /lib/libc.so.6 (0x00007f0dc44cd000)

酒吧:

libkdeui.so.5 => /usr/lib/libkdeui.so.5 (0x00007f716ae22000)
libkio.so.5 => /usr/lib/libkio.so.5 (0x00007f716a96d000)
linux-vdso.so.1 =>  (0x00007fffccffe000)

因此,鉴于上述两个文件,所需实用程序的输出类似于file1:line_number, file2:line_number == matching text (只是一个建议,我真的不在乎语法是什么):

foo:1, bar:3 == linux-vdso.so.1 =>  (0x00007fffccffe000)

谢谢。


@ChristopherSchultz我的错。第一个示例中的第一行应该与第二个示例中的最后一行匹配。感谢您发现错误;变化。
马特·威尔基

1
具有很好的答案另一个类似的问题:unix.stackexchange.com/questions/1079/...
MortezaE

Answers:


210

在* nix上,您可以使用comm。该问题的答案是:

comm -1 -2 file1.sorted file2.sorted 
# where file1 and file2 are sorted and piped into *.sorted

这是的完整用法comm

comm [-1] [-2] [-3 ] file1 file2
-1 Suppress the output column of lines unique to file1.
-2 Suppress the output column of lines unique to file2.
-3 Suppress the output column of lines duplicated in file1 and file2. 

还应注意,如手册页中所述,在使用comm之前对文件进行排序很重要。


3
comm [-1] [-2] [-3] file1 file2 -1抑制file1唯一的行的输出列。-2抑制file2唯一的行的输出列。-3抑制在file1和file2中重复的行的输出列。
ojblass

@ojblass:将此添加到答案中。
Matt J

6
我发现在使用comm之前对文件进行排序很重要。也许将其添加到答案中。
马特·威尔基09年

11
问题的简短答案:comm -1 -2 file1 file2
greggles 2012年

6
如果文件未排序,则可以使用以下命令:comm -1 -2 <(sort filename1)<(sort filename2)
Kevin Wheeler 2015年

56

重复列出的问题上找到了此答案。我发现grep比comm更易于管理,因此,如果您只想要一组匹配行(例如,用于比较CSV),则只需使用

grep -F -x -f file1 file2

或简化的fgrep版本

fgrep -xf file1 file2

另外,您可以file2*用来遍历和查找与多个文件(而不只是两个)相同的行。

其他一些方便的变化包括

  • -n 显示每条匹配行的行号的标志
  • -c 只计算匹配的行数
  • -v仅显示file2中不同的行(或使用diff)。

使用comm速度更快,但是这种速度是以必须首先对文件进行排序为代价的。它作为“反向差异”不是很有用。


谢谢莱德,这对许多人来说比交流更有用。您应该链接到源答案(右侧导航中的Q中有超过六个链接;找到它需要一些工作)。知道grep对未排序或不同排序的输入的效果如何,并且可以打印匹配的相应行号也很高兴。
马特·威尔基

1
@mattwilkie -v在我自己滑倒它之后,我觉得有必要回来并澄清该标志的用法。假设您有两个csv文件file1和file2,并且它们具有重叠行和非重叠行。如果只需要所有不重叠的行,则using fgrep -v file1 file2将只返回file2中的不重叠行,而不会返回file1中的其他不重叠行。对于某些人来说,这可能是显而易见的,但是比起对风险的误解,更好地陈述这一显而易见的事实。在这种情况下,对文件进行排序和使用comm仍然是更好的选择。
莱德(Ryder)

1
感谢您回来并澄清莱德。特别注意和赞赏(所有这些都容易使旧物溜走!)。我切换了可接受的答案,因为comm显然是社区的选择,即使个人进行排序时,我仍然会使用comm。
马特·威尔基

2
使用时的另一个复杂之处是grep:第一个文件中的任何空白行都将与第二个文件中的每一行匹配。确保file1没有空行,否则看起来文件是相同的。
Christopher Schultz

grep -Fxf这是给我的。
loxaxs 18-3-17

35

在此之前被问过:Unix命令在两个文件中查找共同的行

您也可以尝试使用perl(信用在这里

perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/'  file1 file2

1
谢谢。我想接受两个答案,因为perl one衬垫是跨平台的。Comm得到了点头,因为它更简单。
马特·威尔基09年

1
完善。在Windows上使用cygwin终端,comm尚不可用。这是完美的选择。
Qix-蒙尼卡(Monica)

3
这不在乎如何排列行。比通讯更准确。
enl8enmentnow


17

我只是从该线程中学到了comm命令,但想添加一些额外的东西:如果文件未排序,并且您不想触摸原始文件,则可以通过管道传递sort命令的输出。这使原始文件保持不变。在bash中工作,我不能说其他外壳。

comm -1 -2 <(sort file1) <(sort file2)

可以扩展它以比较命令输出,而不是文件:

comm -1 -2 <(ls /dir1 | sort) <(ls /dir2 | sort)

9

最简单的方法是:

awk 'NR==FNR{a[$1]++;next} a[$1] ' file1 file2

文件没有必要进行排序。


1
这与此处的大多数答案不同,因为它允许您重构源模板。我有两个文件是用同一个包装器构建的,在不同点插入了不同的文本。这个答案使我能够恢复包装器。
卢卡斯·贡兹 Lucas Gonze)'17


1

Windows中,可以将Powershell脚本与CompareObject一起使用

compare-object -IncludeEqual -ExcludeDifferent -PassThru (get-content A.txt) (get-content B.txt)> MATCHING.txt | Out-Null #Find Matching Lines

CompareObject:

  • IncludeEqual不带-ExcludeDifferent:一切
  • 不带-InclueEqual的ExcludeDifferent:无
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.