【问题标题】:How to remove dupes from blocks of text如何从文本块中删除欺骗
【发布时间】:2016-06-07 16:56:30
【问题描述】:

什么是删除文本文件中块内的欺骗的聪明而简单的方法。每个块由两个换行符分隔。

之前:

apple
banana
apple
cherry
cherry

delta
epsilon
delta
epsilon

apple pie
delta
delta

之后:

apple
banana
cherry

delta
epsilon

apple pie
delta

谢谢。应该在 Mac 上工作。允许 Unicode。任何 shell 方法/语言/命令。欺骗不一定是连续的。如果您忽略前导/尾随空格,或者可以使用逗号作为记录中的分隔符,则会获得奖励。

【问题讨论】:

    标签: ruby perl awk sed


    【解决方案1】:
    $ awk '!NF{delete seen} !seen[$0]++' file
    apple
    banana
    cherry
    
    delta
    epsilon
    
    apple pie
    delta
    

    使用 GNU awk for gensub()ignore(相对于 remove)前导/尾随空格将是:

    $ awk '!NF{delete seen} !seen[gensub(/^\s+|\s+$/,"","g")]++' file
    

    在这种情况下,我不知道您所说的 can use a comma as the delimiter within a record 是什么意思。

    【讨论】:

    • 嗨,埃德。哇!棒极了!我觉得这是如此简短和优雅,我应该知道它。很好,谢谢。我可以经常使用它。
    • 哦,用逗号,我的意思是也能处理这种格式:apple,banana,apple,banana \n
    • 这也将删除从之前的块中看到的任何项目
    【解决方案2】:

    红宝石!

    text =<<_
    apple
    banana
    apple
    cherry
    cherry
    
    delta
    epsilon
    delta
    epsilon
    
    apple pie
    delta
    delta
    _
    
    r1 = /
         (?<=\n) # match a newline in a positive lookbehind
         \n      # match a newline
         /x      # extended/free-spacing regex definition mode
    
    r2 = /
         (?<=\n) # match a newline in a positive lookbehind
         /x
    
    puts text.split(r1).map { |s| s.split(r2).uniq.join }.join("\n")
      # apple
      # banana
      # cherry
    
      # delta
      # epsilon
    
      # apple pie
      # delta
    

    步骤:

    a = text.split(r1)
      #=> ["apple\nbanana\napple\ncherry\ncherry\n",
      #    "delta\nepsilon\ndelta\nepsilon\n",
      #    "apple pie\ndelta\ndelta\n"] 
    a.map { |s| s.split(r2) }
      #=> [["apple\n", "banana\n", "apple\n", "cherry\n", "cherry\n"],
      #    ["delta\n", "epsilon\n", "delta\n", "epsilon\n"],
      #    ["apple pie\n", "delta\n", "delta\n"]] 
    a.map { |s| s.split(r2).uniq }
      #=> [["apple\n", "banana\n", "cherry\n"],
      #    ["delta\n", "epsilon\n"],
      #    ["apple pie\n", "delta\n"]] 
    b = a.map { |s| s.split(r2).uniq.join }
      #=> ["apple\nbanana\ncherry\n",
      #    "delta\nepsilon\n",
      #    "apple pie\ndelta\n"] 
    b.join("\n")
      #=> "apple\nbanana\ncherry\n\ndelta\nepsilon\n\napple pie\ndelta\n" 
    

    【讨论】:

      【解决方案3】:

      这可能对你有用(GNU sed):

      sed -r ':a;N;s/\b((\S+)\b.*)\n\2$/\1/;/^$/M!ba' file
      

      将行存储在模式空间 (PS) 中,直到出现空行或文件末尾。读取的最后一行和前一行的模式匹配,如果它们匹配,则删除最后一行。如果最后一行是空行(或文件末尾),则打印 PS 中保存的所有行。

      【讨论】:

        【解决方案4】:

        给定:

        $ cat file
        apple
        banana
        apple
        cherry
        cherry
        
        delta
        epsilon
        delta
        epsilon
        
        apple pie
        delta
        delta
        

        您可以使用 Ruby 的段落模式命令行开关让空白行成为每个记录的分隔符,并将每个字段的字段分隔符设置为 \n。然后将每个块唯一化:

        $ ruby -00 -F'\n' -lane '$><<$F.uniq.join("\n")<<"\n\n"' file
        apple
        banana
        cherry
        
        delta
        epsilon
        
        apple pie
        delta
        

        解释:

        $ ruby -00 -F'\n' -lane '$><<$F.uniq.join("\n")<<"\n\n"'
           ^                                                      # ruby 1.9+ only I think
                ^                                                 # split records by \n\n
                    ^                                             # split fields by \n
                           ^                                      # options to:
                                                                    -l loop over input
                                                                     a auto split
                                                                     n don't auto print
                                                                     e compile command line
                                 ^                                # to STDOUT
                                   ^                              # append
                                     ^                            # the split fields
                                         ^                        # made uniq
                                             ^                    # join back to a string
                                                  ^               # add back the record separator   
        

        或者,您可以使用 Ruby 哈希来计算字段,然后只打印哈希的键:

        $ ruby -00 -F'\n' -lane 'h=Hash.new(0)
                                 $F.each {|f| h[f]+=1 }
                                 p h
                                 puts h.keys.join("\n")<<"\n\n"
                                 ' file
        {"apple"=>2, "banana"=>1, "cherry"=>2}
        apple
        banana
        cherry
        
        {"delta"=>2, "epsilon"=>2}
        delta
        epsilon
        
        {"apple pie"=>1, "delta"=>2}
        apple pie
        delta 
        

        (在 ruby​​ 1.9+ 中,哈希保持插入顺序——这将按文件顺序打印单词。)

        如果你想在潜在的字段分隔符中添加,,你可以这样做:

        $ ruby -00 -F'\n|,' -lane '$><<$F.uniq.join("\n")<<"\n\n"' file                         
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-03-07
          • 1970-01-01
          • 2010-10-11
          • 1970-01-01
          • 1970-01-01
          • 2010-11-11
          • 1970-01-01
          相关资源
          最近更新 更多