【问题标题】:Finding Set Complement in Unix在 Unix 中查找集合补码
【发布时间】:2011-01-10 17:25:47
【问题描述】:

鉴于这两个文件:

 $ cat A.txt     $ cat B.txt
    3           11
    5           1
    1           12
    2           3
    4           2

我想在 B 中找到 A“但不是”中的行号。 它的unix命令是什么?

我试过了,但似乎失败了:

comm -3 <(sort -n A.txt) <(sort -n B.txt) | sed 's/\t//g' 

【问题讨论】:

  • 您可能有充分的理由使用 Unix one-liner,但您是否考虑过编写 Perl 或 Python 脚本来实现它?这可以更快地编写并且更容易阅读和修改。 Python 在语言中内置了基于集合的操作,因此只需几行代码,您就可以在这里实现您想要做的事情。
  • @avpx:你是对的。在 Python 中,就像''.join(set(open('A.txt')) - set(open('B.txt'))) 一样简单。
  • @Alok:这是一个很好的方法,当然比我写的要短。赞一个。

标签: linux unix comm set-operations


【解决方案1】:
comm -2 -3 <(sort A.txt) <(sort B.txt)

如果我理解正确的话,应该做你想做的事。

编辑:实际上,comm 需要按字典顺序对文件进行排序,因此您不希望在 sort 命令中使用 -n

$ cat A.txt
1
4
112
$ cat B.txt
1
112
# Bad:
$ comm -2 -3 <(sort -n B.txt) <(sort -n B.txt)
4
comm: file 1 is not in sorted order
112
# OK:
$ comm -2 -3 <(sort A.txt) <(sort B.txt)
4

【讨论】:

    【解决方案2】:

    你可以试试这个

    $ awk 'FNR==NR{a[$0];next} (!($0 in a))' B.txt A.txt
    5
    4
    

    【讨论】:

    • @ghostdog74:奇怪为什么它在我的机器上给出了不同的结果:3、5、1、2、4,
    • 你运行什么操作系统?在 Solaris 上使用 nawk。
    【解决方案3】:

    请注意,awk 解决方案有效,但在 A 中保留了重复项(不在 B 中); python解决方案对结果进行去重

    还要注意comm 不计算真正的集合差异;如果一行在 A 中重复,而在 B 中重复的次数较少,comm 将在结果中留下“额外”行:

    $ cat A.txt 
    120
    121
    122
    122
    $ cat B.txt 
    121
    122
    121
    $ comm -23 <(sort A.txt) <(sort B.txt)
    120
    122
    

    如果不希望出现这种行为,请使用sort -u 删除重复项(仅限 A 中的重复项):

    $ comm -23 <(sort -u A.txt) <(sort B.txt)
    120
    

    【讨论】:

      【解决方案4】:

      I wrote a program recently called Setdown 从 cli 执行 Set 操作。

      它可以通过编写类似于您在 Makefile 中编写的定义来执行集合操作:

      someUnion: "file-1.txt" \/ "file-2.txt"
      someIntersection: "file-1.txt" /\ "file-2.txt"
      someDifference: someUnion - someIntersection
      

      它很酷,你应该去看看。我个人不建议使用不是为作业构建的临时命令来执行集合操作。当您确实需要执行许多集合操作或者您有任何相互依赖的集合操作时,它不会很好地工作。不仅如此,setdown 还允许您编写依赖于其他集合操作的集合操作!

      无论如何,我认为它很酷,您应该完全检查一下。

      注意:我认为 Setdown 比 comm 好得多,因为 Setdown 不需要您正确排序输入。相反,Setdown 将为您对输入进行排序,并使用外部排序。因此它可以处理大量文件。我认为这是一个很大的好处,因为我忘记对传递给 comm 的文件进行排序的次数已经数不胜数了。

      【讨论】:

        【解决方案5】:

        这是使用join 的另一种方法:

        join -v1 <(sort A.txt) <(sort B.txt)
        

        来自documentationjoin

        ‘-v 文件编号’ 为文件 file-number(“1”或“2”)中每个不可配对的行打印一行,而不是正常输出。

        【讨论】:

          猜你喜欢
          • 2011-09-11
          • 1970-01-01
          • 2011-01-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多