我在这里寻找这个,但没有找到确切的情况。对不起,如果它是重复的,但我找不到它。
我在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
有什么办法吗?
谢谢!
答案 0 :(得分:3)
这应该有效
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
答案 1 :(得分:2)
awk -F\# '{ p = ($1 FS $2 in a ); a[$1 FS $2] = $0 }
!p { keys[++k] = $1 FS $2 }
END { for (k = 1; k in keys; ++k) print a[keys[k]] }' file
输出:
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
答案 2 :(得分:2)
首先,您需要对输入文件进行排序以确保行的顺序,例如对于重复的用户名#来源,您将获得订购时间。最好是反过来,所以最后一个事件是第一个。这可以通过简单的排序来完成,例如:
sort -r < yourfile
这将从您的输入产生下一个:
A222222#Windows#2014-08-18#10:47:16
A222222#Juniper#2014-08-08#09:15:34
A222222#Juniper#2014-08-07#14:31:40
A111111#Windows#2014-08-08#10:27:30
A111111#Juniper#2014-08-10#14:32:55
反向排序的行,其中对于每个username#source
组合,最新事件首先出现。
接下来,您需要对排序的行进行一些过滤,以便仅获取第一个事件。这可以使用多个工具完成,例如awk
或uniq
或perl
等等,
所以,解决方案
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
最后,您可以根据需要重新排序唯一的行。
答案 3 :(得分:0)
如果你知道第一列总是7个字符长,第二列也是7个字符长,你可以提取唯一的行,只考虑前16个字符:
uniq file -w 16
由于您希望后者重复,您可以在tac
之前使用uniq
反转数据,然后再次反转输出:
tac file | uniq -w 16 | tac
更新:如下所示,uniq
需要对行进行排序。在这种情况下,这开始变得做作,基于awk
的建议更好。这样的事情仍然有效:
sort -s -t"#" -k1,2 file | tac | uniq -w 16 | tac