Bash 如何按列删除重复项(逆序)
我在这里找过,但没有找到确切的病例。抱歉,如果它是重复的,但我找不到它 我在Debian中有一个巨大的文件,其中包含4列,以“#”分隔,格式如下:Bash 如何按列删除重复项(逆序),bash,sorting,sed,Bash,Sorting,Sed,我在这里找过,但没有找到确切的病例。抱歉,如果它是重复的,但我找不到它 我在Debian中有一个巨大的文件,其中包含4列,以“#”分隔,格式如下: username#source#date#time 例如: A222222#Windows#2014-08-18#10:47:16 A222222#Juniper#2014-08-07#14:31:40 A222222#Juniper#2014-08-08#09:15:34 A111111#Juniper#2014-08-10#14:32:55 A
username#source#date#time
例如:
A222222#Windows#2014-08-18#10:47:16
A222222#Juniper#2014-08-07#14:31:40
A222222#Juniper#2014-08-08#09:15:34
A111111#Juniper#2014-08-10#14:32:55
A111111#Windows#2014-08-08#10:27:30
我希望根据前两列打印唯一的行,如果发现重复项,则必须根据日期/时间打印最后一个事件。根据上述列表,结果应为:
A222222#Windows#2014-08-18#10:47:16
A222222#Juniper#2014-08-08#09:15:34
A111111#Juniper#2014-08-10#14:32:55
A111111#Windows#2014-08-08#10:27:30
我使用两个命令对其进行了测试:
cat file | sort -u -t# -k1,2
cat file | sort -r -u -t# -k1,2
但它们都打印了以下内容:
A222222#Windows#2014-08-18#10:47:16
A222222#Juniper#2014-08-07#14:31:40 --> Wrong line, it is older than the duplicate one
A111111#Juniper#2014-08-10#14:32:55
A111111#Windows#2014-08-08#10:27:30
有什么办法吗
谢谢 如果您知道第一列的长度始终为7个字符,第二列的长度也为7个字符,那么您可以提取唯一的行,只考虑前16个字符:
uniq file -w 16
由于您需要后一个副本,因此可以在uniq
之前使用tac
反转数据,然后再次反转输出:
tac file | uniq -w 16 | tac
更新:如下所述,uniq
需要对行进行排序。在这种情况下,这开始变得人为,基于awk
的建议更好。不过,类似的方法仍然有效:
sort -s -t"#" -k1,2 file | tac | uniq -w 16 | tac
输出:
A222222#Windows#2014-08-18#10:47:16
A222222#Juniper#2014-08-08#09:15:34
A111111#Juniper#2014-08-10#14:32:55
A111111#Windows#2014-08-08#10:27:30
这应该行得通
tac file | awk -F# '!a[$1,$2]++' | tac
输出
A222222#Windows#2014-08-18#10:47:16
A222222#Juniper#2014-08-08#09:15:34
A111111#Juniper#2014-08-10#14:32:55
A111111#Windows#2014-08-08#10:27:30
首先,您需要对输入文件进行排序,以确保行的顺序,例如,对于重复的username#source,您将获得排序次数。最好是反向排序,所以最后一个事件优先。这可以通过简单的排序完成,如:
sort -r < yourfile
逆序行,其中对于每个username#source
组合,最新事件排在第一位
接下来,您需要对排序的行进行某种程度的过滤,以仅获取第一个事件。这可以通过几种工具来实现,如awk
或uniq
或perl
等
那么,解决方案呢
sort -r <yourfile | uniq -w16
以上所有内容将在下一页打印
A222222#Windows#2014-08-18#10:47:16
A222222#Juniper#2014-08-08#09:15:34
A111111#Windows#2014-08-08#10:27:30
A111111#Juniper#2014-08-10#14:32:55
最后,您可以根据需要对唯一行重新排序。您说得对。这与问题描述不符。我将删除这个答案。谢谢。很抱歉,“源”列可能会有所不同,因此此解决方案对我无效。仅当输入中的事件按升序排列时,此解决方案才有效。请始终使用
!看到[$1,$2]+
,而不是!查看[$1$2]+
。考虑每一种方法会发生什么,如果一行从<代码>一个BC 开始,另一个用“代码> AB<C</代码>。@ EdMordon哦,是的,我现在会改变它。@ JM666是真的,虽然它看起来是一个日志问题,最有可能是按日期排序(假设),所以这应该正确地工作(希望)。.第二个效果很好,但第三个也很好。这将用于非常大的文件,哪个文件的性能更好?谢谢:)@alesnav不知道,但是你可以自己测试速度;)我不在办公室,明天将测试:)始终使用!看到[$1,$2]+
,而不是!查看[$1$2]+
。考虑每一种方法会发生什么,给定一行从<代码>一个BC < /代码>和另一个代码< ab > C <代码> > @艾德莫顿,你绝对正确!将编辑答案。它确实有效,但我不知道当处理一个50k行的文件时它的性能是否正常。。。我明天会测试:)
sort -r <yourfile | uniq -w16
sort -r <yourfile | awk -F# '!seen[$1,$2]++'
sort -r yourfile | perl -F'#' -lanE 'say $_ unless $seen{"$F[0],$F[1]"}++'
A222222#Windows#2014-08-18#10:47:16
A222222#Juniper#2014-08-08#09:15:34
A111111#Windows#2014-08-08#10:27:30
A111111#Juniper#2014-08-10#14:32:55