是否有一种工具可以使一个文件中的行不在另一个文件中?


Answers:


159

是。grep用于在文件中搜索文本字符串的标准工具可用于从一个文件中减去所有文件中的所有行。

grep -F -x -v -f fileB fileA

通过将fileB中的每一行用作模式(-f fileB),并将其视为要匹配的纯字符串(而不是常规正则表达式)(-F)来工作。您强制匹配发生在整行(-x)上,并仅打印不匹配的行(-v)。因此,您正在打印出fileA中不包含与fileB中任何行相同数据的行。

该解决方案的缺点是,它没有考虑行顺序,如果您的输入在不同的地方有重复的行,您可能无法获得预期的结果。解决方案是使用真正的比较工具,例如diff。您可以通过创建一个diff文件,其上下文值位于文件中100%的行中,然后将其解析为仅将文件A转换为文件B时要删除的行。(请注意,此命令还删除了diff得到正确的行后进行格式化。)

diff -U $(wc -l < fileA) fileA fileB | sed -n 's/^-//p' > fileC

@ inderpreet99小写-u参数实际上确实接受一个数字参数,只要它后面没有空格即可。我以前使用它的方式的优点是它可以有或没有值都可以工作,因此您可以在该子命令例程中使用一些不返回值的东西。另一方面,大写字母“ -U”需要一个参数。
Caleb

要小心,grep的-f是O(N ^ 2)I相信:stackoverflow.com/questions/4780203/...
rogerdpack

1
diff管道工程款待表示感谢。
费利佩·阿尔瓦雷斯

为了解决排序问题,您可以根据需要在命令中使用进程替换来处理每个文件grep。范例:grep -F -x -v -f <(sort fileB) <(sort fileA)
Tony Cesaro

@TonyCesaro如果您的数据集不是特定于订单的,并且不需要考虑重复项,那将起作用。使用的优点diff是考虑了文件中的位置。
卡雷布(Caleb),

57

答案很大程度上取决于您要比较的文件的类型和格式。

如果您要比较的文件是已排序的文本文件,那么Richard Stallman和Davide McKenzie编写的GNU工具comm可能会执行您要执行的过滤。它是coreutils的一部分。

假设您有以下2个文件:

$ cat a
1
2
3
4
5

$ cat b
1
2
3
4
5
6

文件b中不存在的行a

$ comm <(sort a) <(sort b) -3
    6

1
+1提及comm; 不幸的是,comm需要分类的文件
Arcege'2

11
这样排序吗?comm <(sort a)<(sort b)-1 -2
Sirex '02

这是一些奇怪的语法。<()?它有效,我明白了,但是这种怪异有名字吗?
mlissner '17

2
@mlissner <()也称为流程替换
miku

1
comm最初是由贝尔实验室的某人而不是rms于1973年撰写的。您指的是后来出现的GNU实现。多年来,Unix实用程序有许多不同的实现。
斯特凡Chazelas

32

stackoverflow ...

通讯-23 file1 file2

-23抑制两个文件中或仅在文件2中的行。文件必须进行排序(它们在您的示例中),但如果不是,则首先通过排序将它们通过管道传送...

此处查看手册页


这并不为我工作,出于某种原因...

@Jan您的文件已排序?您如何对它们进行排序?
JJS


4

如果文件很大,而您的条目没有自定义顺序,则grep花费的时间太长。一个快速的替代方法是

sort file1 > 1 
sort file2 > 2 
diff 1 2 | grep "\>" | sed -e 's/> //'

[file2-file1结果显示到屏幕,管道传输到文件等。]

更改><将会得到相反的减法。rm 1 2


2

您也可以考虑vimdiff,它突出显示了vim编辑器中文件之间的差异。


1
但是,有没有一种简单的方法可以自动在Vimdiff中进行减法?
卡扎尔克
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.