【问题标题】:Remove partial duplicates from text file从文本文件中删除部分重复项
【发布时间】:2016-04-14 09:30:00
【问题描述】:

我的 bash-foo 现在有点生锈了,所以我想看看是否有一种聪明的方法可以从文件中删除部分重复项。我有一堆包含数千行的文件,格式如下:

String1|String2|String3|String4|String5|String6|...|String22|09-Apr-2016 05:28:03|x

本质上它是一堆用管道分隔的字符串,最后两列是时间戳和 x。我想做的是连接我的所有文件,然后删除所有部分重复。我将部分重复定义为文件中从 String1 到 String22 匹配的一行,但时间戳可以不同。

例如,一个文件包含:

String1|String2|String3|String4|String5|String6|...|String22|09-Apr-2016 05:28:03|x
String1|String2|String3|String4|String5|String6|...|String22|09-Apr-2016 12:12:12|x
String124|String2|String3|String4|String5|String6|...|String22|09-Apr-2016 05:28:03|x

会变成:

String1|String2|String3|String4|String5|String6|...|String22|09-Apr-2016 05:28:03|x
String124|String2|String3|String4|String5|String6|...|String22|09-Apr-2016 05:28:03|x

(选择哪个时间戳无关紧要)。

有什么想法吗?

【问题讨论】:

    标签: bash awk


    【解决方案1】:

    使用awk 你可以这样做:

    awk '{k=$0; gsub(/(\|[^|]*){2}$/, "", k)} !seen[k]++' file
    
    String1|String2|String3|String4|String5|String6|String7|09-Apr-2016 05:28:03|x
    String124|String2|String3|String4|String5|String6|String7|09-Apr-2016 05:28:03|x
    

    awk 命令首先通过删除每行的最后两个字段来创建变量k。然后它使用关联数组seen,键为k,通过将每个进程的键存储在数组中,它只打印键的第一个实例。

    【讨论】:

      【解决方案2】:

      如果您有支持关联数组的 Bash 版本 4,则可以在纯 Bash 中相当高效地完成:

      declare -A found
      while IFS= read -r line || [[ -n $line ]] ; do
          strings=${line%|*|*}
          if (( ! ${found[$strings]-0} )) ; then
              printf '%s\n' "$line"
              found[$strings]=1
          fi
      done < "$file"
      

      【讨论】:

      【解决方案3】:

      与@anubhava 的想法相同,但我认为更惯用

      $ awk -F'|' '{line=$0;$NF=$(NF-1)=""} !a[$0]++{print line}' file
      
      String1|String2|String3|String4|String5|String6|...|String22|09-Apr-2016 05:28:03|x
      String124|String2|String3|String4|String5|String6|...|String22|09-Apr-2016 05:28:03|x
      

      【讨论】:

      • 这不太惯用(惯用的数组名称是seen[],您不想硬编码要设置为空的字段列表)而且它很脆弱,因为它将替换所有| $0 中的 s 带有空白字符,因此您无法再将 a|b ca b|c 区分开来 - 当在 a[$0]++ 中使用时,它们都会变为 a b c
      猜你喜欢
      • 2013-03-27
      • 2013-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-17
      • 2015-08-29
      • 2018-02-05
      相关资源
      最近更新 更多