【问题标题】:How to completely erase the duplicated lines by linux tools?如何通过linux工具完全擦除重复的行?
【发布时间】:2017-04-16 10:53:16
【问题描述】:

这个问题不等于How to print only the unique lines in BASH?,因为那个问题建议删除重复行的所有副本,而这个问题只是关于消除重复行,即将1, 2, 3, 3 更改为1, 2, 3 而不是只是1, 2

这个问题真的很难写,因为我看不出任何有意义的东西。但这个例子显然是直截了当的。如果我有这样的文件:

1
2
2
3
4

解析文件后删除重复的行,变成这样:

1
3
4

我知道 python 或其中的一些,这是我编写的用于执行它的 python 脚本。创建一个名为clean_duplicates.py 的文件并将其运行为:

import sys

#
# To run it use:
# python clean_duplicates.py < input.txt > clean.txt
#
def main():

    lines = sys.stdin.readlines()

    # print( lines )
    clean_duplicates( lines )

#
# It does only removes adjacent duplicated lines, so your need to sort them
# with sensitive case before run it.
# 
def clean_duplicates( lines ):

    lastLine    = lines[ 0 ]
    nextLine    = None
    currentLine = None
    linesCount  = len( lines )

    # If it is a one lined file, to print it and stop the algorithm
    if linesCount == 1:

        sys.stdout.write( lines[ linesCount - 1 ] )
        sys.exit()

    # To print the first line
    if linesCount > 1 and lines[ 0 ] != lines[ 1 ]:

        sys.stdout.write( lines[ 0 ] )

    # To print the middle lines, range( 0, 2 ) create the list [0, 1]
    for index in range( 1, linesCount - 1 ):

        currentLine = lines[ index ]
        nextLine    = lines[ index + 1 ]

        if currentLine == lastLine:

            continue

        lastLine = lines[ index ]

        if currentLine == nextLine:

            continue

        sys.stdout.write( currentLine )

    # To print the last line
    if linesCount > 2 and lines[ linesCount - 2 ] != lines[ linesCount - 1 ]:

        sys.stdout.write( lines[ linesCount - 1 ] )

if __name__ == "__main__":

    main()

虽然,在搜索重复行时,删除似乎更容易使用 grep、sort、sed、uniq 等工具:

  1. How to remove duplicate lines inside a text file?
  2. removing line from list using sort, grep LINUX
  3. Find duplicate lines in a file and count how many time each line was duplicated?
  4. Remove duplicate entries in a Bash script
  5. How to delete duplicate lines in a file without sorting it in Unix?
  6. How to delete duplicate lines in a file...AWK, SED, UNIQ not working on my file

【问题讨论】:

  • 重复行总是相邻吗?假设输入是 1, 2, 2, 3, 4, 2 - 4 之后的 2 是否应该出现在输出中?
  • 是的,我在做之前对它们进行了排序,以便于编写代码。无论如何,最好是马上使用uniq -u
  • 请注意,给定输入 1、2、2、3、4、2、uniq -u 将打印第二个 2;它仅适用于相邻的重复行。因此,预分类是一个好主意。另请注意,uniq 采用零个或一个输入文件,如果有输入文件,它可以采用输出文件:uniq [-c|-d|-u] [-f fields] [-s char] [input_file [output_file]] 根据 POSIX。它不是通用文件过滤器(通用文件过滤器采用零个或多个文件名并依次处理标准输入或每个文件名,写入标准输出)。
  • 谢谢! uniq 文档具有误导性。我在这里测试过,它只删除相邻的行。
  • 这能回答你的问题吗? How to print only the unique lines in BASH?

标签: python awk sed grep uniq


【解决方案1】:

您可以将uniq-u/--unique 选项一起使用。根据uniq man page

-u/--unique

不要输出在输入中重复的行。
仅打印 INPUT 中唯一的行。

例如:

cat /tmp/uniques.txt | uniq -u

或者,如UUOC: Useless use of cat 中所述,更好的方法是:

uniq -u /tmp/uniques.txt

这两个命令都会返回值:

1
3
4

其中 /tmp/uniques.txt 包含问题中提到的数字,即

1
2
2
3
4

注意:uniq 要求对文件内容进行排序。正如doc中提到的:

默认情况下,uniq 打印排序文件中的唯一行,它会丢弃所有相同的连续输入行。以便 OUTPUT 包含唯一的行。

如果文件没有排序,你需要先sort内容 然后在排序后的内容上使用uniq

sort /tmp/uniques.txt | uniq -u

【讨论】:

  • @JonathanLeffler:感谢您分享信息。更新了答案
  • @EdMorton:是的,我想这是我错过的一条非常重要的信息,因为相关文件的内容已经排序。更新了答案
【解决方案2】:

无需排序,输出顺序与输入顺序相同:

$ awk 'NR==FNR{c[$0]++;next} c[$0]==1' file file
1
3
4

【讨论】:

    【解决方案3】:
    Europe Finland Office Supplies Online H 5/21/2015 193508565 7/3/2015 2339 651.21 524.96 1523180.19 1227881.44 295298.75
    Europe Greece Household Online L 9/11/2015 895509612 9/26/2015 49 668.27 502.54 32745.23 24624.46 8120.77
    Europe Hungary Beverages Online C 8/21/2012 722931563 8/25/2012 370 47.45 31.79 17556.50 11762.30 5794.20
    Europe Hungary Beverages Online C 8/21/2012 722931563 8/25/2012 370 47.45 31.79 17556.50 11762.30 5794.20
    

    如果你有这种线,你可以使用这个命令。

    [isuru@192 ~]$ sort duplines.txt | sed 's/\ /\-/g' | uniq | sed 's/\-/\ /g'    
    

    但在使用特殊字符时请记住。如果您的行中有破折号,请确保使用不同的符号。在这里,我在反斜杠和正斜杠之间保留一个空格。

    Before applied the code

    After applied the code

    【讨论】:

      【解决方案4】:

      请使用带有-u 参数的sort 命令来列出任何命令输出的唯一值。

          cat file_name |sort -u
      1
      2
      3
      4
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-21
      • 2020-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-27
      • 2018-01-27
      相关资源
      最近更新 更多