【问题标题】:Sort two files in Linux and find lines unique to each file在 Linux 中对两个文件进行排序并找到每个文件唯一的行
【发布时间】:2016-03-02 18:41:45
【问题描述】:

我有 2 个文件。

File1 内容如下:

000000513609200,238/PLMN/000100
000000513609200,238/PLMN/000200
000050354428060,238/PLMN/000200
000050354428060,238/PLMN/000100
001212131415120,238/PLMN/000100
...
...

文件2内容:

000000513609200,238/PLMN/000100
000000513609200,238/PLMN/000200
000050354428060,238/PLMN/000200
000050354428060,238/PLMN/000100
001212131415120,238/PLMN/000100
...
...

File1 有接近 15000 条记录,file2 有接近 20000 条记录。我想找到仅存在于 file1 或 file2 中的行(记录)。我正在使用以下内容:

comm -3 <(sort file1) <(sort file2) > file6

这是一个好的选择吗?

此外,排序如何与这些记录一起工作?它将如何理解将哪一列作为主键?

您还可以建议一个简单的 awk 脚本来比较 file1 和 file2 并将仅存在于 file1 或仅存在于 file2 中的行转发到 file7,以便我可以比较输出。我想确保我的 comm 产生相同的结果。

【问题讨论】:

  • sort 没有选项会直接按字母顺序排序。没有字段,没有列。只有字符串要比较。如果还不够好,您可以指定各种 cli 选项。 man sort 会解释其中的一部分。
  • 您的输出文件是否与file6(或您的文本中的file7)而不是更明显的file3 相关?我想知道您是否打算比较两个以上的文件,并希望建立一个只比较 2 个文件的解决方案。
  • 注意comm -3输出中的缩进

标签: linux shell sorting awk


【解决方案1】:

使用 awk 无需排序即可:

awk 'FNR==NR {
   a[$0]
   next
}
{
   if ($0 in a)
      delete a[$0]
   else
      print
}
END {
   for (i in a)
      print i
}' file1 file2

同样使用grep,您也可以使用:

{ grep -vxFf file1 file2; grep -vxFf file2 file1; }

【讨论】:

  • @dig_123,我怀疑 awk 答案可能比 comm 答案更快,因为您不必进行任何排序。
  • 只是我的意见,但是:您最近似乎采用了一种非常奇怪的编码风格 - 我从未见过任何基于 Algol 的语言的代码,其中 { 在同一行后面跟随其他一些代码意味着您引入的代码块以外的任何内容,该代码块的执行在某种程度上依赖于或至少与前面的代码块相关联。在同一行使用 { 和终止 } 在 awk 中特别容易混淆,因为它是 &lt;condition&gt; { &lt;action&gt; } 范式,新手已经难以理解。
  • 是的,我认为你有一个公平的观点。这些习惯来自我整天的 Java 编码,其中 else {else if { 必须放在前面 if 块的关闭 } 的同一行上,否则它会在自动构建时显示为代码分析中的一个未解决问题Sonarqube
【解决方案2】:

这使用 -u(唯一)标志进行排序并删除任一文件中的所有重复项。

sort -u file1 file2 > file6

【讨论】:

  • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。 meta.stackoverflow.com/a/300846/4231110
  • @JustinHoward 谢谢。是的,我可以更详细。编辑我的答案。
【解决方案3】:

如果我理解正确,只需根据任何“列”对行进行排序,您可以:

sort file1 file2 -t '/' -k 3 > file6

其中-t '/'指定列分隔符,-k 3指定基于此分隔符的列号。

至于第二个问题,如果你只是想比较文件,你可以试试 diff 命令看看对你有没有帮助。

【讨论】:

    【解决方案4】:

    如果文件已排序(或可以即时排序),您也可以尝试加入。由于您没有良好的测试输入,我将在一个玩具示例中展示

    $ seq 5 > f1
    $ seq 3 9 > f2
    

    这给出了两个文件中的公共记录,与comm -12 f1 f2 相同

    $ join f1 f2  
    3
    4
    5
    

    这给出了两个文件中不匹配的记录,与comm -3 f1 f2 | sed 's/^\t//' 相同

    $ join -v1 -v2 f1 f2
    1
    2
    6
    7
    8
    9
    

    【讨论】:

      猜你喜欢
      • 2011-12-03
      • 1970-01-01
      • 2021-12-13
      • 2013-01-02
      • 1970-01-01
      • 2021-05-21
      • 1970-01-01
      • 1970-01-01
      • 2016-03-27
      相关资源
      最近更新 更多