【发布时间】:2011-05-31 11:47:04
【问题描述】:
我想比较 file1 和 file2 并生成一个 file3,其中包含 file1 中 file2 中不存在的行。
【问题讨论】:
-
我尝试了 diff,但它会在不同的行前面生成一些数字和其他符号,这让我很难比较文件。
我想比较 file1 和 file2 并生成一个 file3,其中包含 file1 中 file2 中不存在的行。
【问题讨论】:
diff(1) 不是答案,但 comm(1) 是。
NAME
comm - compare two sorted files line by line
SYNOPSIS
comm [OPTION]... FILE1 FILE2
...
-1 suppress lines unique to FILE1
-2 suppress lines unique to FILE2
-3 suppress lines that appear in both files
所以
comm -2 -3 file1 file2 > file3
输入文件必须排序。如果不是,请先对它们进行排序。这可以通过临时文件来完成,或者...
comm -2 -3 <(sort file1) <(sort file2) > file3
前提是您的 shell 支持进程替换(bash 支持)。
【讨论】:
comm -23
Unix 实用程序 diff 正是为此目的而设计的。
$ diff -u file1 file2 > file3
有关选项、不同的输出格式等,请参阅手册和 Internet。
【讨论】:
考虑一下:
文件 a.txt:
abcd
efgh
文件b.txt:
abcd
您可以通过以下方式找到不同之处:
diff -a --suppress-common-lines -y a.txt b.txt
输出将是:
efgh
您可以使用以下命令重新定向输出文件 (c.txt) 中的输出:
diff -a --suppress-common-lines -y a.txt b.txt > c.txt
这将回答你的问题:
"...其中包含 file1 中的行 文件 2 中不存在。”
【讨论】:
-d,这将使diff尽最大努力找到可能的最小差异。 -i、-E、-w、-B 和 --suppress-blank-empty 偶尔也会有用,但并非总是如此。如果您不知道什么适合您的用例,请先尝试diff --help(当您不知道命令可以做什么时,这通常是个好主意)。
有时diff 是您需要的实用程序,但有时join 更合适。文件需要预先排序,或者,如果您使用支持进程替换的 shell,例如 bash、ksh 或 zsh,您可以即时进行排序。
join -v 1 <(sort file1) <(sort file2)
【讨论】:
但是,没有grep 解决方案?
仅存在于 file2 中的行:
grep -Fxvf file1 file2 > file3
仅存在于 file1 中的行:
grep -Fxvf file2 file1 > file3
两个文件中都存在的行:
grep -Fxf file1 file2 > file3
【讨论】:
试试
sdiff file1 file2
在大多数情况下,它通常对我来说效果更好。 如果行的顺序不重要(例如某些文本配置文件),您可能需要先对文件进行排序。
例如,
sdiff -w 185 file1.cfg file2.cfg
【讨论】:
sdiff <(sort file1) <(sort file2))
已经有很多答案了,但没有一个是完美的恕我直言。 Thanatos 的回答每行留下一些额外的字符,而 Sorpigal 的回答要求对文件进行排序或预排序,这在所有情况下可能都不够用。
我认为获得不同的行的最佳方式(没有额外的字符,没有重新排序)是diff、grep 和awk(或类似)的组合。
如果行不包含任何“
diff urls.txt* | grep "<" | sed 's/< //g'
但这会从行中删除“
diff urls.txt* | grep "<" | awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}'
这个单行比较两个文件,然后过滤掉 diff 的 ed 样式输出,然后删除 diff 添加的尾随“
【讨论】:
您可以使用具有以下输出格式的diff:
diff --old-line-format='' --unchanged-line-format='' file1 file2
--old-line-format='',如果文件 2 中的行不同,则禁用文件 1 的输出。--unchanged-line-format='',如果行相同,则禁用输出。
【讨论】:
我很惊讶没有人提到 diff -y 来产生并排输出,例如:
diff -y file1 file2 > file3
而在file3(不同的行中间有一个符号|):
same same
diff_1 | diff_2
【讨论】:
使用 Diff 实用程序并仅提取输出中以
【讨论】:
diff a1.txt a2.txt | grep '> ' | sed 's/> //' > a3.txt
我尝试了该线程中的几乎所有答案,但没有一个是完整的。经过几条以上的路线对我有用。 diff 会给你带来不同,但会有一些不需要的特殊字符。您实际的差异线以“>”开头。所以下一步是 grep 行以 '> ' 开头,然后用 sed 删除相同的行。
【讨论】:
< 开头的行。如果您交换输入文件的顺序,您将看到这一点。即使您这样做了,您也希望通过使用更多 sed 来省略 grep:` diff a1 a2 | sed '/> /s///'` 这仍然可以在正确的情况下中断包含> 或< 的行,并且仍然 留下额外的行号描述行。如果您想尝试这种方法,更好的方法是:diff -C0 a1 a2 | sed -ne '/^[+-] /s/^..//p'。
如果您有一个包含单列甚至多列的 CSV 文件,您可以使用 sqlite3 嵌入式数据库逐行执行这些“差异”操作。它带有 python,所以应该可以在大多数 linux/macs 上使用。您可以在 bash shell 上编写 sqlite3 命令脚本,而无需编写 python。
echo "
.mode csv
.import a.csv atable
.import b.csv btable
create table result as select * from atable EXCEPT select * from btable;
.output result.csv
select * from result ;
.quit
" | sqlite3 temp.db
注意:确保每个 sqlite3 命令都有一个换行符。
它是如何工作的
如果你需要对特定的列进行操作,sqlite3 或任何 db 都是可行的。
我尝试使用内置的 diff 和 comm 工具对多个 GB 文件进行比较。 Sqlite 比 linux 实用程序领先一英里。
【讨论】: