从文本文件中删除部分重复项

时间:2016-04-13 17:02:13

标签: bash awk

我的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

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

有什么想法吗?

3 个答案:

答案 0 :(得分:3)

使用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命令首先通过从每行中删除最后2个字段来生成变量k。然后它使用一个关联数组seen,其键为k,它通过将每个进程键存储在数组中来打印第一个键实例。

答案 1 :(得分:0)

如果你有支持关联数组的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"

答案 2 :(得分:0)

与@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