【问题标题】:removing duplicate lines from file /grep从文件 /grep 中删除重复的行
【发布时间】:2009-09-17 16:11:29
【问题描述】:

我想删除所有第二列 05408736032 相同的所有行

0009300|05408736032|89|01|001|0|0|0|1|NNNNNNYNNNNNNNNN|asdf| 0009367|05408736032|89|01|001|0|0|0|1|NNNNNNNYNNNNNNNNNN|adff|

这些行不是连续的。删除所有线条很好。我不必保留其中一个。

对不起,我的 unix fu 真的很弱,因为不使用:)。

【问题讨论】:

标签: unix shell scripting sorting


【解决方案1】:

如果您的所有输入数据都按上述格式进行格式化 - 即固定大小的字段 - 并且输出中的行顺序无关紧要,sort --key=8,19 --unique 应该可以解决问题。如果顺序确实重要,但重复的行总是连续的,uniq -s 8 -w 11 将起作用。如果字段不是固定宽度但重复的行总是连续的,那么 Pax 的 awk 脚本将起作用。不过,在最一般的情况下,我们可能会看到一些对于单线来说有点过于复杂的东西。

【讨论】:

    【解决方案2】:

    假设它们是连续的并且你想删除后续的,下面的 awk 脚本会做到这一点:

    awk -F'|' 'NR==1 {print;x=$2} NR>1 {if ($2 != x) {print;x=$2}}'
    

    它通过打印第一行并存储第二列来工作。然后对于后续行,它会跳过存储值和第二列相同的行(如果不同,则打印该行并更新存储值)。

    如果它们不是连续的,我会选择 Perl 解决方案,您可以在其中维护一个关联数组来检测和删除重复项 - 我会对其进行编码,但我 3 岁的女儿刚刚醒来,现在是午夜,她已经感冒了——明天见,如果我能熬过那晚:-)

    【讨论】:

      【解决方案3】:

      这是用于删除行中重复单词的代码..

      awk '{for (i=1; i<=NF; i++) {x=0; for(j=i-1; j>=1; j--) {if ($i == $j){x=1} } if( x != 1){printf ("%s ", $i) }}print ""}' sent
      

      【讨论】:

        【解决方案4】:

        如果列不固定宽度,仍然可以使用排序:

        sort -t '|' --key=10,10 -g FILENAME
        
        1. -t 标志将设置分隔符。
        2. -g 仅用于自然数字排序。

        【讨论】:

        • 使用 '-k' 以获得最大(POSIX 兼容)可移植性(并且没有 '=')。另外,为什么第二列是 10,10?
        • 两个原因。一,当您使用 -t 排序时,将使用字段而不是字符(即 10 不是更高的数字)。二,结束 (,10) 被指定为停止使用从该点开始的其余行进行排序。
        【解决方案5】:

        Unix 包含 python,因此以下几行代码可能正是您所需要的:

        f=open('input.txt','rt')
        d={}
        for s in f.readlines():
          l=s.split('|')
          if l[2] not in d:
            print s
            d[l[2]]=True
        

        这无需固定长度即可工作,即使相同的值不是邻居。

        【讨论】:

        • 这不会删除所有具有重复值的行——它会打印第一个实例。
        • 确实如此。问题是“可以删除所有实例”-因此不需要删除所有实例,可以为每个实例留下一个代表。至少,我是这么理解的。
        【解决方案6】:

        此 awk 将仅打印第二列不是 05408736032 的那些行

        awk '{if($2!=05408736032}{print}' filename
        

        【讨论】:

        • 您需要在数字周围加上引号吗?由于前导零,它是否被解释为八进制数?或者它不会因为出现 8 而被解释为八进制(当然在八进制中无效),但是如果数字中没有 8 或 9 怎么办?
        【解决方案7】:

        对输入文件进行两次遍历:1) 查找重复值,2) 删除它们

        awk -F\| '
            {count[$2]++} 
            END {for (x in count) {if (count[x] > 1) {print x}}}
        ' input.txt >input.txt.dups
        
        awk -F\| '
            NR==FNR {dup[$1]++; next}
            !($2 in dup) {print}
        ' input.txt.dups input.txt
        

        如果你使用bash,你可以省略临时文件:使用进程替换合并成一行:(深呼吸)

        awk -F\| 'NR==FNR {dup[$1]++; next} !($2 in dup) {print}' <(awk -F\| '{count[$2]++} END {for (x in count) {if (count[x] > 1) {print x}}}' input.txt) input.txt
        

        (呼!)

        【讨论】:

          【解决方案8】:
          awk -F"|" '!_[$2]++' file
          

          【讨论】:

            【解决方案9】:

            将行放入散列中,使用行作为键和值,然后遍历散列(这应该适用于几乎任何编程语言,awk,perl 等)

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2014-06-03
              • 2018-01-31
              • 2010-11-17
              • 1970-01-01
              • 2019-02-18
              相关资源
              最近更新 更多