Bash 如何按列删除重复项(逆序)

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

我在这里找过,但没有找到确切的病例。抱歉,如果它是重复的,但我找不到它

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