我的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
(选择哪个时间戳无关紧要)。
有什么想法吗?
答案 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)
$ 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