Awk 如何使用grep对列表进行排序,以根据预定义列表显示唯一出现的次数?
假设我有一个列表,看起来像这样 example.txt:Awk 如何使用grep对列表进行排序,以根据预定义列表显示唯一出现的次数?,awk,grep,Awk,Grep,假设我有一个列表,看起来像这样 example.txt: 2010-01-06 15:03:14 57.55.24.13 user1 2010-01-07 20:02:14 69.54.12.36 user2 2010-01-08 12:34:34 127.21.159.2 user3 2010-01-08 02:43:45 116.40.11.179 user1 user1 user2 user3 列表中有一组给定的用户和他们使用的ip地址。我想做的是找到每个用户登录的唯一IP地址的数量
2010-01-06 15:03:14 57.55.24.13 user1
2010-01-07 20:02:14 69.54.12.36 user2
2010-01-08 12:34:34 127.21.159.2 user3
2010-01-08 02:43:45 116.40.11.179 user1
user1
user2
user3
列表中有一组给定的用户和他们使用的ip地址。我想做的是找到每个用户登录的唯一IP地址的数量。因此,在前面的示例中,user1将返回值2。但是,如果user1从116.40.11.179再次登录,结果仍然是2,因为它不是唯一的ip
我试着列出用户名
userlist.txt:
2010-01-06 15:03:14 57.55.24.13 user1
2010-01-07 20:02:14 69.54.12.36 user2
2010-01-08 12:34:34 127.21.159.2 user3
2010-01-08 02:43:45 116.40.11.179 user1
user1
user2
user3
然后我试着用类似的东西把它传给grep
grep example.txt | uniq -c | wc -l < userlist.txt
grep example.txt | uniq-c | wc-l
但这显然不是很好。有什么想法吗
awk '
{
u = $4
ip = $3
if (!s[u,ip]++)
cnt[u]++
}
END {
for (u in cnt)
print u, cnt[u]
}
' input.file
输出
user1 2
user2 1
user3 1
你能试试下面的吗
awk '
!seen[$NF OFS $(NF-1)]++{
user[$NF]++
}
END{
for(key in user){
print key,user[key]
}
}
' Input_file
输出如下
user1 2
user2 1
user3 1
对于阵列阵列,使用GNU awk:
$ awk '{usrs_ips[$4][$3]} END{for (usr in usrs_ips) print usr, length(usrs_ips[usr])}' file
user1 2
user2 1
user3 1
使用支持长度(数组)的awk:
对于任何awk:
$ sort -k4,4 file | awk '
$4 != prev { if (NR>1) print prev, cnt; prev=$4; delete seen; cnt=0 }
!seen[$3]++ { cnt++ }
END { print prev, cnt }
'
user1 2
user2 1
user3 1
最后两个解决方案比第一个和目前发布的其他解决方案都有好处,它们没有将每个用户+ip组合存储在内存中,但这只有在输入文件很大的情况下才有意义 执行此操作的工具是uniq。您需要应用uniq两次:第一次按用户和IP对example.txt的条目进行分组,第二次用于计数 所以不需要在AWK中重新编码,即使这可以以非常漂亮的方式完成。但是,我将使用AWK对字段进行重新排序:
awk '{print $4, $3}' example.txt | sort | uniq | awk '{print $1}' | uniq -c
不需要单独的userlist.txt文件。一个非
awk
示例,使用GNU,这是一个非常有用的工具,用于执行以下列数据组的操作:
$ datamash -Ws -g4 countunique 3 < example.txt
user1 2
user2 1
user3 1
$datamash-Ws-g4 countunique 3
对于第4列中具有相同值的每个组,它将在第3列中打印唯一出现的值的数量。请在您的问题中提及预期的输出,然后让我们知道。@RavinderSingh13输出将是(#出现次数)因此,对于我的代码示例,应该是user12或user1,无论哪个更有效,其他人的答案也有效,但他们发布得更快。Ryan Ravinder和@slitvinov的解决方案是相同的,只是slitvinov使用了两个变量来保存$NF和$(NF-1)的值,将测试/条件放在操作区域而不是条件区域,并且不使用惯用的
!在测试中看到[keys]+
。if(!((u,ip)in s)){s[u,ip];cnt[u]+}
通常/习惯性地写为if(!看到[u,ip]+){cnt[u]+}
sort | uniq
=sort-u
如果首先使用sort-k4,4-k3,3-u文件| awk'{print$4}进行排序,则可以进一步减少对awk的管道和调用事实上你根本不需要awk:sort-k4,4-k3,3-u文件| cut-d'-f4 | uniq-c
效率更高,因为cut
比awk
每输入行的工作量要少得多。不错的方法,顺便说一句。@EdMorton:这太棒了!顺便说一下,我没想到你会提出一个无awk的解决方案。我使用awk是为了可读性。我只使用最适合这项工作的工具(sed、grep、cut等等),只是当人们在这里发布关于操纵文本的问题时,通常是为了一些非琐碎的东西,然后最好的解决方案通常是awk。因此,从我对通常标有awk:-)的问题的回答中,您对我使用的工具有一个偏颇的看法。在这种情况下,我只是没有首先想到排序|切割| uniq
方法!