【问题标题】:bash: Difference between join and commbash:join 和 comm 的区别
【发布时间】:2011-08-29 18:12:31
【问题描述】:
# comm -12 /tmp/src /tmp/txt | wc -l
  10338
# join /tmp/src /tmp/txt | wc -l
  10355

这两个文件都是单列字母数字字符串和sort-ed。他们不应该一样吗?


更新以下@Kevin-s 的回答:

cat /tmp/txt | sed 's/^[:space:]*//' > /tmp/stxt
cat /tmp/src | sed 's/^[:space:]*//' > /tmp/ssrc

结果:

#join /tmp/ssrc /tmp/stxt | wc -l
516
# comm -12 /tmp/ssrc /tmp/stxt | wc -l
513

在手动检查diff-s ... 由于sed 未删除一些空格,结果有所不同。

【问题讨论】:

  • 这真的不是一个 bash 问题。
  • @keith Thompson 这可能是特定于命令的 - 但我在为 bash 脚本选择它们时遇到了它们。因此标签。

标签: bash join comm


【解决方案1】:

commjoin 之间存在一些差异:

  1. comm 比较整行; join 比较行内的字段。
  2. comm 打印整行; join 可以打印选定的部分行。

当每个文件中只有一列数据时,差异相对较小。当您有多个列时,可能会有很大差异。

另请注意,在适当的情况下,join 可以从一个文件输出多个数据副本,同时连接来自另一个文件的不同行。在我看来,这就像您的问题;您可能在其中一个文件中有一些重复的值。假设你有:

src           txt
123           123
              123
              123

如果你做comm -12 src txt,你会得到一行输出;如果你做join src txt,你会得到三行输出。这是意料之中的。

join 命令还可以处理“外连接”,即第一个文件中的一行的第二个文件中缺少数据(SQL 中的左外连接)或反之亦然(右外连接),或同时两者(完全外连接)。

总而言之,join 是一个更复杂的命令,但它正在尝试执行更复杂的工作。两者都有用;但它们在不同的地方都有用。

【讨论】:

  • 感谢您的回答,非常有用。我通常在专栏上使用sort -k,但从来没有习惯使用join - 并且发现自己正在编写长条awk 关联数组来比较文件.. lulz:D
【解决方案2】:

join 的主要用途是选择共享一个字段的行,就像在数据库中一样。假设您有以下文件:

File A
Alice  24
Bill   16
Claire 31
John   10
John  -14

File B
Bill   Copenhagen
John   Adelaide

...您可以通过将文件 B 作为要加入的文件并将两者的第一个字段作为要加入的字段来从文件 A 中选择“John”和“Bill”行。但是,这两个文件都必须在该字段上进行排序的要求在实践中相当麻烦。

【讨论】:

    【解决方案3】:

    我没有广泛使用过,但是从快速查看手册页和测试输入来看,如果两个文件不同,comm 会同时打印这两个文件,而 join 只会打印匹配的行。 -12 解决了这个问题。您可以将两者的输出存储到文件中并进行比较以查看它们的不同之处。

    $ echo -e '1\n2\n3\n5' > a
    $ echo -e '1\n2\n4\n5' > b
    $ comm a b
                    1
                    2
    3
            4
                    5
    $ join a b
    1
    2
    5
    $
    

    编辑: Join 只比较第一个空格分隔的字段,但 comm 比较整行。因此,行上的任何空格都会使输出不同。

    【讨论】:

    • 我正在使用 comm -12 来抑制 FILE1、FILE2 独有的行。 diff-s 太大了 - 伤眼睛 ;)
    • 我知道我错过了。在进一步查看手册页之后,似乎 join 在第一个空格分隔的字段上连接,但 comm 在整行上连接。输入文件中有空格吗?
    • 好点...我会尝试sed 增加空格,看看是否有区别...:D
    • 问题确实是由于胭脂空白造成的。使用对文件所做的更改更新了问题。我现在在手动检查中发现的结果之间的细微差别都是因为空格 - 想知道为什么 [:space:] 没有删除它们。 Anyregex,您能否更新您的答案以便我接受?非常感谢:D
    • 我知道 rouge 是法语中红色的意思,但我不知道 -s to diff 的作用。
    【解决方案4】:

    使用[[:space:]](而不是[:space:])用sed去除空格。

    # compare
    {
    echo '   abc' | sed 's/^[:space:]*//'
    echo '   abc' | sed 's/^[[:space:]]*//'
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-07
      • 2011-10-20
      • 2020-01-23
      • 1970-01-01
      • 2020-03-07
      • 1970-01-01
      • 2014-10-09
      • 2010-12-21
      相关资源
      最近更新 更多