【问题标题】:How to keep a file's format if you use the uniq command (in shell)?如果使用 uniq 命令(在 shell 中),如何保持文件的格式?
【发布时间】:2010-10-13 04:33:57
【问题描述】:

要使用 uniq 命令,您必须先对文件进行排序。

但是在我拥有的文件中,信息的顺序很重要,如何保持文件的原始格式但仍然摆脱重复的内容?

【问题讨论】:

  • 你想只保留模式的第一次出现吗?还是只有最后一个?你必须比这更具体一点......
  • 文件是这样的。模式1 模式2 模式3 模式4 模式1 模式2 等等... 模式1 与模式2 不同,等等。例如)pattern1 是标题,pattern2 是电话号码。如果我对文件进行排序,电话号码将不在正确的标题下,等等。
  • 我忘记了这个评论部分没有保留格式。所以上面的帖子可能有点难以理解。
  • 很多答案。午饭回来后,我会检查它们并选择最佳答案。谢谢大家。

标签: unix file shell sorting duplicates


【解决方案1】:

另一个 awk 版本:

awk '!_[$0]++' infile

【讨论】:

  • 仅在第一次看到时打印。
【解决方案2】:

awk 保留第一次出现。与其他答案使用的算法相同:

awk '!($0 in lines) { print $0; lines[$0]; }'

这里只需要使用awk 存储重复的行(而不是所有行):

sort file | uniq -d | awk '
   FNR == NR { dups[$0] }
   FNR != NR && (!($0 in dups) || !lines[$0]++)
' - file

【讨论】:

    【解决方案3】:

    还有“行号,双重排序”方法。

     nl -n ln | sort -u -k 2| sort -k 1n | cut -f 2-
    

    【讨论】:

    • +1 用于处理非常大文件的解决方案。但这不应该是“sort -k 1n”(数字排序)吗?
    【解决方案4】:

    您可以在文件的排序版本上运行 uniq -d 以查找重复的行,然后运行一些脚本:

    if this_line is in duplicate_lines {
        if not i_have_seen[this_line] {
            output this_line
            i_have_seen[this_line] = true
        }
    } else {
        output this_line
    }
    

    【讨论】:

    • 与稍微简单的解决方案相比,这样做的好处是,您不必保留文件中每一行的映射,只保留重复的行。
    • 哦等等。没想到 -d 。傻傻的。好吧,可以删除通讯然后转而支持它:)
    • 最终版本放入 -d 而不是使用 comm: sort file.txt |唯一的-d | awk 'FNR==NR { 重复[$0]; } FNR!=NR { if($0 in dups) { if(!($0 in lines)) { print $0;行[$0]; } } 否则打印 $0; }' - 文件.txt
    【解决方案5】:

    仅使用 uniq 和 grep:

    创建 d.sh:

    #!/bin/sh
    sort $1 | uniq > $1_uniq
    for line in $(cat $1); do
    cat $1_uniq | grep -m1 $line >> $1_out
    cat $1_uniq | grep -v $line > $1_uniq2
    mv $1_uniq2 $1_uniq
    done;
    rm $1_uniq
    

    示例:

    ./d.sh infile
    

    【讨论】:

      【解决方案6】:

      你可以使用一些可怕的 O(n^2) 的东西,像这样(伪代码):

      file2 = EMPTY_FILE
      for each line in file1:
        if not line in file2:
          file2.append(line)
      

      这可能相当慢,尤其是在 Bash 级别实现时。但是,如果您的文件相当短,它可能工作得很好,并且可以快速实施(not line in file2 就是 grep -v,等等)。

      否则你当然可以编写一个专门的程序,在内存中使用一些更高级的数据结构来加速它。

      【讨论】:

      • 感谢放松。我现在拥有的文件只是一个示例文件,所以它很短。但是我将使用它的文件会很大。我会看看其他人的建议,我现在可能会尝试你的建议。
      【解决方案7】:
      for line in $(sort file1 | uniq ); do
          grep -n -m1 line file >>out
      done;
      
      sort -n out
      

      首先进行排序,

      对于第一个匹配的每个 uniqe 值 grep (-m1)

      并保留行号

      按行号对输出进行数字排序(-n)。

      然后您可以使用 sed 或 awk 删除 # 行

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-02-14
        • 2014-05-01
        • 2012-03-16
        • 2016-07-24
        • 1970-01-01
        • 2012-03-12
        • 2017-12-24
        相关资源
        最近更新 更多