【问题标题】:awk how to remove duplicates in fields only if previous fields are the sameawk如何仅在先前字段相同的情况下删除字段中的重复项
【发布时间】:2011-01-25 04:38:39
【问题描述】:

我试图从字段中删除重复项(并将它们替换为空白),前提是之前的字段相同。例如:

示例输入:

France  Paris      Museum of Fine Arts          blabala
France  Paris      Museum of Fine Arts          blajlk
France  Paris      Yet another museum           lqmsjdf
France  Paris      Museum of National History            mlqskjf
France  Bordeaux   Museum of Fine Arts          qsfsqf
France  Bordeaux   City Hall                lmqjflqsk
France  Bordeaux   City Hall                    lqkjfqlskjflqskfj
Spain   Madrid     Museum of Fine Arts          lqksjfh
Spain   Madrid     Museum of Fine Arts          qlmfjlqsjf
Spain   Barcelona  City Hall                nvqjvvnqk
Spain   Barcelona  Museum of Fine Arts          lmkqjflqksfj

期望的输出:

France    Paris        Museum of FineArts                    blabala
                                                             blajlk
                       Yet another museum                    lqmsjdf
                       Museum of National History            mlqskjf
          Bordeaux     Museum of Fine Arts                   qsfsqf
                       City Hall                             lmqjflqsk
                                                             lqkjfqlskjflqskfj
Spain     Madrid       Museum of Fine Arts                   lqksjfh
                                                             qlmfjlqsjf
          Barcelona   City Hall                              nvqjvvnqk
                      Museum of Fine Arts                    lmkqjflqksfj

非常感谢您的任何帮助。

【问题讨论】:

  • 您可能可以在awk 中使用函数来执行此操作,但为什么呢?它似乎更适合更通用的语言。也许 Python 使用 csv 模块?此外,除非这是最后一步,否则这可能不是一个好主意,因为这会使将来解析文件变得更加困难。
  • 我有一个在这里完成几乎相同的脚本:stackoverflow.com/questions/4785566/…,但我必须保留经常回来的机构的名称。所以需要时间来隔离它们(1500行)。至于输出,它符合我的目的,因为该文件在某处被处理为 LaTeX。
  • 这是指向当前页面的链接。也许你的意思是this question
  • 记录是否有序?具体来说,“法国巴黎还……”会不会出现在两个“法国巴黎博物馆……”之间?此外,字段是否以制表符分隔(除了字段内没有空格,字段内没有制表符)?
  • @Dennis:是的,我的意思是那个脚本!到目前为止,我就是这样完成工作的,直到我意识到我可以做得更好(嗯……“某人”可以做得更好)。那时我还没有完全分析问题(实际上是被淹没了)。是的,数据已排序。

标签: awk duplicates


【解决方案1】:

试试这个:

awk -F '\t' 'BEGIN {OFS=FS} {if ($1 == prev1) $1 = ""; else prev1 = $1; if ($2 == prev2) $2 = ""; else prev2 = $2; if ($3 == prev3) $3 = ""; else prev3 = $3; print}' inputfile

这是适用于任意数量字段的较短版本(始终打印最后一个字段):

awk -F '\t' 'BEGIN {OFS=FS} {for (i=1; i<=NF-1;i++) if ($i == prev[i]) $i = ""; else prev[i] = $i; print}' inputfile

输出不会对齐以供屏幕使用,但会有正确数量的选项卡。

输出将如下所示:

field1 TAB field2 TAB field3 TAB field4
TAB TAB TAB field4
TAB TAB field3 TAB field4
TAB field2 TAB field3 TAB field4
etc.

如果您需要对齐列,这也是可能的。

编辑:

此版本允许您指定要删除重复的字段:

#!/usr/bin/awk -f
BEGIN {
    FS="\t"; OFS=FS
    deduplist=ARGV[1]
    ARGV[1]=""
    split(deduplist,tmp," ")
    for (i in tmp) dedup[tmp[i]]=1
}
{
    for (i=1; i<=NF;i++)
        if (i in dedup) {
            if ($i == prev[i])
                $i = ""
            else
                prev[i] = $i
        }
    # prevent printing lines that are completely blank because 
    # it's an exact duplicate of the preceding line and all fields 
    # are being deduplicated
    if ($0 !~ /^[[:blank:]]*$/) 
        print
}

像这样运行它:./script.awk "2 3" inputfile 去重复字段 2 和 3。

【讨论】:

  • 第一个脚本根本不起作用。第二个效果很好,只是它会导致“更多”字段出现问题,因为它们可能包含我想要保留的复制数据(即“信件”、“报告”……)。换句话说,我宁愿能够控制我删除重复的字段(但你仍然是我的天才!)。
  • @Trying:这很奇怪,因为两者基本上在做同样的事情。请参阅我的新版本,了解如何选择要删除重复项的字段。
  • 效果很好。多么棒的剧本!它非常灵活。这可能使我成为(小)工作场所(仍然很低的薪水)中每个人都需要的女人。由于我不知道如何感谢您(除了将答案标记为已接受),这里是我对您的小小感谢:i.imgur.com/G7UE2.jpg我的主管很棒。如果她以她想要的方式获得该死的 pdf,我会深入研究,这是因为丹尼斯威廉姆森,她只能感谢我加班(但是,我迟到了!--嘿,不能两全其美!)
【解决方案2】:

试试这个 Perl 单行:

perl  -F"\t" -nae '@O=@F;if(!$x){$x=1}else{for($i=0;$i<=$#S;$i++){$F[$i]=""if($S[$i] eq "" || $S[$i] eq $F[$i])}};print join "\t",@F;@S=@O;'

See it

我假设这些字段是制表符分隔的。

【讨论】:

  • 脚本对我不起作用。它只是在第二次出现时缩进第一个字段。这是我第一次使用 perl...
  • @Trying:输入是制表符分隔的吗?我已经给出了一个关于 ideone 的工作链接,请查看。
猜你喜欢
  • 1970-01-01
  • 2022-01-04
  • 2012-10-31
  • 1970-01-01
  • 2018-11-03
  • 2011-05-22
  • 2021-05-28
  • 2016-02-21
  • 2016-10-06
相关资源
最近更新 更多