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

mat*_*kie 165 diff command-line

我有一系列的我想要为哪知道普通的线,而不是它们之间的不同线路的文本文件.命令行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)
Run Code Online (Sandbox Code Playgroud)

酒吧:

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

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

foo:1, bar:3 == linux-vdso.so.1 =>  (0x00007fffccffe000)
Run Code Online (Sandbox Code Playgroud)

谢谢.

Dan*_*Lew 200

在*nix上,您可以使用comm.这个问题的答案是:

comm -1 -2 file1.sorted file2.sorted 
# where file1 and file2 are sorted and piped into *.sorted
Run Code Online (Sandbox Code Playgroud)

以下是完整用法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. 
Run Code Online (Sandbox Code Playgroud)

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

  • 简短回答问题:comm -1 -2 file1 file2 (11认同)
  • 我发现在使用comm之前对文件进行排序很重要.或许将其添加到答案中. (5认同)
  • 如果您的文件没有排序,您可以使用它:comm -1 -2 <(sort filename1)<(sort filename2) (4认同)
  • comm [-1] [-2] [-3] file1 file2 -1抑制file1特有的行的输出列.-2禁止file2特有的行的输出列.-3禁止file1和file2中重复的行的输出列. (3认同)

Ryd*_*der 48

列为重复的问题上找到此答案.我发现grep比comm更加管理友好,所以如果你只想要一组匹配行(比如用于比较CSV),那么只需使用

grep -F -x -f file1 file2
Run Code Online (Sandbox Code Playgroud)

或简化的fgrep版本

fgrep -xf file1 file2
Run Code Online (Sandbox Code Playgroud)

另外,您可以使用file2*glob来查找与多个文件共同的行,而不仅仅是两个.

其他一些方便的变化包括

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

使用comm速度更快,但速度的代价是必须先对文件进行排序.它作为"反向差异"并不是很有用.

  • 谢谢莱德,这对很多人来说可能比通讯更有用。您应该链接到源答案(右侧导航栏中的 Q 中有超过六个链接;查找起来需要一些工作)。如果能知道 grep 对未排序或不同排序的输入的处理效果如何,并且可以打印匹配的相应行号,那就太好了。 (2认同)
  • @mattwilkie 我觉得有必要在我自己滑倒后回来澄清`-v` 标志的使用。假设您有两个 csv 文件 file1 和 file2,它们都有重叠和非重叠的行。如果您想要所有且仅不重叠的行,则使用 `fgrep -v file1 file2` 将只返回 file2 中的非重叠行,*并且不返回 file1* 中的任何其他非重叠行。这对某些人来说可能是显而易见的,但最好陈述显而易见的事情而不是冒着误解的风险。在这种特殊情况下,对文件进行排序并使用 `comm` 仍然是更好的选择。 (2认同)
  • 感谢您回来澄清莱德。额外的关注会被注意到并受到赞赏(这一切都很容易让旧的东西溜走!)。我已经改变了接受的答案,因为 comm 显然是社区的选择,尽管我个人在排序是不必要的开销时仍然使用它。 (2认同)
  • 使用`grep`时的另一个复杂因素:第一个文件中的任何空行都将匹配第二个文件中的每一行.确保`file1`没有空行,或者看起来文件是相同的. (2认同)

Chr*_*heD 34

之前被问到这里:Unix命令找到两个文件中常见的行

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

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

  • 这并不关心线的排序方式.它比comm更准确. (3认同)

Gre*_*ler 16

我刚刚从这个线程学习了comm命令,但是想要添加一些额外的东西:如果文件没有排序,并且你不想触摸原始文件,你可以管道sort命令的outptut.这使原始文件保持不变.在bash中工作,我不能说其他贝壳.

comm -1 -2 <(sort file1) <(sort file2)
Run Code Online (Sandbox Code Playgroud)

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

comm -1 -2 <(ls /dir1 | sort) <(ls /dir2 | sort)
Run Code Online (Sandbox Code Playgroud)


Gur*_*ngh 8

我认为diff实用程序本身,使用其统一的(-U)选项,可以用来实现效果。因为 diff 输出的第一列标记了该行是添加还是删除,所以我们可以查找未更改的行。

diff -U1000 file_1 file_2 | grep '^ '
Run Code Online (Sandbox Code Playgroud)

数字 1000 是任意选择的,大到足以大于任何单个输出块diff

这是完整、万无一失的命令集:

f1="file_1"
f2="file_2"

lc1=$(wc -l "$f1" | cut -f1 -d' ')
lc2=$(wc -l "$f2" | cut -f1 -d' ')
lcmax=$(( lc1 > lc2 ? lc1 : lc2 ))

diff -U$lcmax "$f1" "$f2" | grep '^ ' | less

# Alternatively, use this grep to ignore the lines starting
# with +, -, and @ signs.
#   grep -vE '^[+@-]'
Run Code Online (Sandbox Code Playgroud)

如果您想包含刚刚移动的行,您可以在比较之前对输入进行排序,如下所示:

f1="file_1"
f2="file_2"

lc1=$(wc -l "$f1" | cut -f1 -d' ')
lc2=$(wc -l "$f2" | cut -f1 -d' ')
lcmax=$(( lc1 > lc2 ? lc1 : lc2 ))

diff -U$lcmax <(sort "$f1") <(sort "$f2") | grep '^ ' | less
Run Code Online (Sandbox Code Playgroud)


Gop*_*opu 7

最简单的方法是:

awk 'NR==FNR{a[$1]++;next} a[$1] ' file1 file2
Run Code Online (Sandbox Code Playgroud)

文件无需排序.

  • 这与此处的大多数答案不同,它允许您重建源模板。我有两个由同一个包装器构建的文件,在几个点插入了不同的文本。这个答案使我能够恢复包装器。 (3认同)