代码之家  ›  专栏  ›  技术社区  ›  Adam Matan

bash,linux:设置两个文本文件之间的差异

  •  55
  • Adam Matan  · 技术社区  · 15 年前

    我有两个文件 A - nodes_to_delete B - nodes_to_keep . 每个文件都有许多带有数字标识的行。

    我想知道 要删除的节点 但不在 要保留的节点 例如 alt text http://mathworld.wolfram.com/images/equations/SetDifference/Inline1.gif .

    在postgresql数据库中进行这项工作是不合理的缓慢。在bash中使用linux cli工具有什么好方法吗?

    更新: 这看起来像是一个变态的工作,但文件真的,真的很大。我已经解决了一些类似的问题 uniq , sort 以及一些集合论技巧。这比数据库中的等价物快了两三个数量级。

    5 回复  |  直到 6 年前
        1
  •  87
  •   msw    6 年前

    这个 comm 指挥部做到了。

        2
  •  34
  •   slinkp    8 年前

    几个月前有人在上海教我怎么做,但我一时找不到…我在看的时候无意中发现了你的问题。这里是:

    set_union () {
       sort $1 $2 | uniq
    }
    
    set_difference () {
       sort $1 $2 $2 | uniq -u
    }
    
    set_symmetric_difference() {
       sort $1 $2 | uniq -u
    }
    
        3
  •  4
  •   activedecay    8 年前

    使用 comm -它将逐行比较两个排序的文件

    下面是使用此示例设置对OP问题的回答。 此命令将返回deletenodes独有的行,而不是keepnodes中的行

    comm -1 -3 <(sort keepNodes) <(sort deleteNodes)
    

    说明:显示deletenodes特有的行,隐藏其他行


    示例设置

    我们将使用keepnodes和deletenodes。它们被用作未排序的输入。

    $ cat > keepNodes <(echo bob; echo amber;)
    $ cat > deleteNodes <(echo bob; echo ann;)
    

    默认情况下,comm不带参数打印3列

    unique_to_FILE1
        unique_to_FILE2
            lines_appear_in_both
    

    这是一个赤裸裸的例子 康姆 没有争论。注意这三列。

    $ 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
    

    当你忘记分类的时候,它会优雅地失败。

    comm: file 1 is not in sorted order

        4
  •  3
  •   John B    8 年前

    comm 是专门为这种用例设计的,但它需要排序输入。

    awk 可以说是一个更好的工具,因为它可以很直接地找到设置差异,不需要 sort ,并提供额外的灵活性。

    awk 'NR == FNR { a[$0]; next } !($0 in a)' nodes_to_keep nodes_to_delete
    

    例如,您可能只希望在表示非负数的行中找到差异:

    awk -v r='^[0-9]+$' 'NR == FNR && $0 ~ r {
        a[$0]
        next
    } $0 ~ r && !($0 in a)' nodes_to_keep nodes_to_delete
    
        5
  •  1
  •   Dark Castle    15 年前

    也许你需要一个更好的方法在postgres中完成它,我敢打赌你不会找到一个更快的方法来使用平面文件。您应该能够执行一个简单的内部连接,并假设两个id列都被索引,这应该非常快。