【问题标题】:print duplicate entries without deleting unix/linux打印重复条目而不删除 unix/linux
【发布时间】:2019-01-14 01:04:31
【问题描述】:

假设我有一个这样的文件,有 2 列

    56-cde
    67-cde
    56-cao
    67-cgh
    78-xyz
    456-hhh
    456-jjjj
    45678-nnmn
    45677-abdc
    45678-aief

我试图得到这样的输出:

    56-cde
    56-cao
    67-cde
    67-cgh
    456-hhh
    456-jjjj
    45678-aief
    45678-nnmn

所以基本上不是打印出我需要打印重复项的唯一值:

我尝试像这样使用 awk 来完成此操作:

    cat input.txt | awk -F"-" '{print $1,$2}' | sort -n | uniq -w 2 -D

毫无疑问,这向我展示了第 1 列中的哪些值已重复,并且还显示了第 1 列的重复值以及相应的第 2 列值。但由于我将字节数硬编码为 2,因此它仅显示第一列中 2 位数字的重复值。有没有办法使用 awk 做到这一点?

提前致谢。

【问题讨论】:

    标签: unix awk


    【解决方案1】:

    查看您的 uniq 是否有 -D 选项。我的 cygwin 版本可以:

    cat input.txt | sort | uniq -w 2 -D
    

    【讨论】:

    • 非常感谢。另外,如果我需要通过不硬编码字节数来进行改进,即如果第一列的数字范围为 1-5 位,我应该对上述命令进行哪些修改?
    【解决方案2】:

    另一个没有数组的 awk 解决方案(但有预排序)

     sort -n file | awk -F- '
           NR==1{p=$1; a=$0; c++; next} 
           p==$1{a=a RS $0; c++; next} 
               c{print a} 
                {a=$0; p=$1; c=0} 
             END{if(c) print a}'
    

    【讨论】:

      【解决方案3】:

      这就是我想出的(只是一个 awk 程序,没有外部排序,uniq 等):

      BEGIN { FS = "-" }
      
      { arr[$1] = arr[$1] "-" $2  }
      
      END { 
          for (i in arr) {
              if ((n = split(arr[i], a)) < 3) continue
              for (j = 2; j <= n; ++j)
                  print i"-"a[j]
          }
      }
      

      它收集所有数字以及附加的不同字符串 在arr 中(假设字符串不包含破折号-)。

      使用 gawk,您可以使用数组的数组以避免连接和用破折号分割。

      【讨论】:

        【解决方案4】:

        我将通过预处理数据来处理可变位数的情况,以便数字字段一个固定的大宽度(并在 uniq 中使用该宽度):

        cat input.txt | awk -F- '{printf "%12d-%s\n",$1,$2}'| sort | uniq -w 12 -D
        

        如果您还需要左对齐输出,只需执行此后处理步骤:

        | awk '{print $1}'
        

        【讨论】:

          【解决方案5】:

          使用 Perl

          $ cat two_cols.txt
          56-cde
          67-cde
          56-cao
          67-cgh
          78-xyz
          456-hhh
          456-jjjj
          45678-nnmn
          45677-abdc
          45678-aief
          
          $ perl -F"-" -lane ' @t=@{$kv{$F[0]}}; push(@t,$_); $kv{$F[0]}=[@t]; END { while(($x,$y)=each(%kv)){ print join("\n",@{$y}) if scalar @{$y}>1 }} ' two_cols.txt
          67-cde
          67-cgh
          56-cde
          56-cao
          456-hhh
          456-jjjj
          45678-nnmn
          45678-aief
          
          $
          

          【讨论】:

            猜你喜欢
            • 2018-05-24
            • 2017-08-20
            • 1970-01-01
            • 2021-01-22
            • 1970-01-01
            • 2018-10-16
            • 2010-12-17
            • 2014-12-28
            • 1970-01-01
            相关资源
            最近更新 更多