【问题标题】:Sort and remove duplicates based on column根据列排序和删除重复项
【发布时间】:2013-07-25 02:02:11
【问题描述】:

我有一个文本文件:

$ cat text
542,8,1,418,1
542,9,1,418,1
301,34,1,689070,1
542,9,1,418,1
199,7,1,419,10

我想根据第一列对文件进行排序并使用sort 删除重复项,但事情并没有按预期进行。

方法一

$ sort -t, -u -b -k1n text
542,8,1,418,1
542,9,1,418,1
199,7,1,419,10
301,34,1,689070,1

不是根据第一列排序。

方法2

$ sort -t, -u -b -k1n,1n text
199,7,1,419,10
301,34,1,689070,1
542,8,1,418,1

它删除了542,9,1,418,1 行,但我想保留一份。

似乎第一种方法删除了重复但排序不正确,而第二种方法排序正确但删除了我想要的更多。我应该如何得到正确的结果?

【问题讨论】:

    标签: bash shell sorting


    【解决方案1】:

    问题在于,当您向sort 提供key 时,系统会查找该特定字段的唯一匹配项。由于显示了542,8,1,418,1 行,sort 将接下来的以542 开头的两行视为重复行并将它们过滤掉。

    最好的办法是对所有列进行排序:

    sort -t, -nk1,1 -nk2,2 -nk3,3 -nk4,4 -nk5,5 -u text
    

    或

    使用awk 过滤重复行并将其通过管道传输到sort。

    awk '!_[$0]++' text | sort -t, -nk1,1
    

    【讨论】:

    • uniq 要求对输入文件进行排序。 sort 基于第 1 列的输出是否有可能未根据所有列排序?
    • 我的猜测是,如果我可以使用 -nk1,5 根据 (1,2,3,4,5) 进行排序,那么 uniq 应该可以工作,但由于某些加密原因,它不能工作。
    • @Yang 嗯,您也可以使用awk '!_[$0]++' text | sort -t, -nk1,1 来先过滤重复行,然后通过管道对其进行排序。
    • 谢谢这成功了。我还有一个问题,为什么-nk1,5 不起作用?它应该首先根据 1 排序,然后是 2 等,但输出类似于方法 1。
    • @Yang 这不是正确的排序方式。您必须使用sort -t, -nk1,1 -nk2,2 -nk3,3 -nk4,4 -nk5,5 -u text 对所有列进行排序,然后从中列出unique 行。
    【解决方案2】:

    在对键进行排序时,您还必须提供键的结尾,否则排序也会使用所有后续键。

    以下应该有效:

    sort -t, -u -k1,1n text
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-09
      • 2017-03-02
      • 2018-07-09
      • 2011-02-09
      • 1970-01-01
      • 2017-11-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多