bash,Linux:设置两个文本文件的区别
我有两个文件A
– nodes_to_delete
和B
– nodes_to_keep
。 每个文件都有许多带有数字ID的行。
我想拥有nodes_to_delete
中的数字id的列表,但不包含在nodes_to_keep
,例如alt text http://mathworld.wolfram.comhttp://img.dovov.comequations/SetDifference/Inline1.gif 。
在PostgreSQL数据库中执行它是不合理的。 任何使用Linux CLI工具在bash中完成的方式?
更新:这似乎是一个Pythonic的工作,但文件是真的,真的很大。 我用uniq
, sort
和一些理论技巧解决了一些类似的问题。 这比数据库等效的速度要快两到三个数量级。
comm命令做到这一点。
几个月前,有人向我展示了如何做到这一点,然后我找不到一段时间……而看着我偶然发现你的问题。 这里是 :
set_union () { sort $1 $2 | uniq } set_difference () { sort $1 $2 $2 | uniq -u } set_symmetric_difference() { sort $1 $2 | uniq -u }
我脑海中的第一件事是:
diff nodes_to_delete nodes_to_keep | grep '<'
我在编辑之前已经回答了,所以我不认为这可能仍然适用,如果你发现数据库的方式是慢的…
也许你需要一个更好的方式来做到这一点在postgres,我敢打赌,你不会find一个更快的方式来使用平面文件。 你应该能够做一个简单的内部连接,并假设这两个id cols索引应该是非常快的。
使用comm
– 它将逐行比较两个sorting的文件
以下是使用此示例设置的OP问题的答案。 这个命令将返回deleteNodes的唯一行,不在keepNodes中
comm -1 -3 <(sort keepNodes) <(sort deleteNodes)
解释:显示deleteNodes的唯一行,隐藏其他行
示例设置
我们将使用keepNodes和deleteNodes。 它们被用作未sorting的input。
$ cat > keepNodes <(echo bob; echo amber;) $ cat > deleteNodes <(echo bob; echo ann;)
默认情况下没有参数,通讯打印3列
unique_to_FILE1 unique_to_FILE2 lines_appear_in_both
这是没有参数的comm
一个准系统例子。 注意三列。
$ comm <(sort keepNodes) <(sort deleteNodes) amber ann bob
抑制列输出
用-N抑制第1,2或3列; 注意当一列被隐藏时,空白会缩小。
$ comm -1 <(sort keepNodes) <(sort deleteNodes) ann bob $ comm -2 <(sort keepNodes) <(sort deleteNodes) amber bob $ comm -3 <(sort keepNodes) <(sort deleteNodes) amber ann $ comm -1 -3 <(sort keepNodes) <(sort deleteNodes) ann $ comm -2 -3 <(sort keepNodes) <(sort deleteNodes) amber $ comm -1 -2 <(sort keepNodes) <(sort deleteNodes) bob
当您忘记sorting时,它会优雅地失败
comm: file 1 is not in sorted order
comm
是专门为这种用例devise的,但它需要分类input。
awk
可以说是一个更好的工具,因为它是相当直接的发现集合差异,不需要sort
,并提供了额外的灵活性。
awk 'NR == FNR { a[$0]; next } !($0 in a)' nodes_to_keep nodes_to_delete
也许,例如,您只想find表示非负数的行的差异:
awk -vr='^[0-9]+$' 'NR == FNR && $0 ~ r { a[$0] next } $0 ~ r && !($0 in a)' nodes_to_keep nodes_to_delete