替代uniq -c并在纯awk中排序

时间:2015-07-21 01:06:00

标签: macos bash sorting awk uniq

这是一个命令,用于从access.log文件中过滤掉IP地址的命中数,然后计算每个IP的命中数,并将它们从最低到最高计数排序:

awk '{print $1}' "${ACCESSLOG}" | sort -n | uniq -c | sort -nk1

这里是结果的摘录:

 26 45.59.193.115
 26 74.125.63.33
 27 88.156.36.194
 28 12.208.4.156
 29 12.208.4.156
 31 98.236.117.199
 32 176.9.82.6
 33 187.34.167.111
 35 67.110.83.252
 37 54.184.4.183
 39 195.59.2.173
 39 70.199.109.118
 44 12.208.4.156
 59 88.156.36.194

现在是否可以通过仅使用awk获得相同的结果? 没有uniq -c,没有排序。

似乎无法在网上找到有关此内容的更多信息......

3 个答案:

答案 0 :(得分:4)

理论上 - 是的,你可以。但这里有两个部分:

你能实现sort和uniq吗?排序将非常棘手,但可以肯定的是,您可以在awk中实现任何内容。 Uniq应该是微不足道的。

你能实现你的管道,所以 Meteor.subscribe(elemId, function() { Session.set(elemId, true); console.log("subscribed"); var end = new Date().getTime(); console.log(end - start); children = items.find(); }); 正是如此。是的,而且不会很难。只需使用:

| uniq -c | sort -nk1 | uniq

这是计数/ uniq部分。您必须添加awk '{ips[$1]++} END {for (ip in ips) { print ips[ip], ip}}' 以对结尾处的条目进行排序。

答案 1 :(得分:1)

GNU awk具有使计数和排序变得容易的功能:

awk 'BEGIN{PROCINFO["sorted_in"]="@val_num_asc"} { a[$1]++ } END{for (ip in a)print a[ip],ip}' access.log

语句PROCINFO["sorted_in"]="@val_num_asc"导致数组按值排序,而不是键,按数字升序排序。

(Mac OSX上的默认awk是BSD,所以不要在那里试试。)

实施例

假设我们有输入文件:

$ cat access.log
74.125.63.33
45.59.193.115
45.59.193.115
74.125.63.33
74.125.63.33
74.125.63.33
195.59.2.173

然后上面产生:

$ awk 'BEGIN{PROCINFO["sorted_in"]="@val_num_asc"} { a[$1]++ } END{for (ip in a)print a[ip],ip}' access.log
1 195.59.2.173
2 45.59.193.115
4 74.125.63.33

答案 2 :(得分:1)

@viraptor实际上,我更正了我的命令,因为我们的结果都不同,现在看起来更像是这样:

awk '{print $1}' "${ACCESSLOG}" | sort -n | uniq -c | sort -nk1

真实0m0.020s

用户0m0.016s

sys 0m0.012s

所以我将sort命令添加到你的初始命题,因为我既不能使用gawk(asort)也不能使用GNU:

awk '{if(ips[$1]) {ips[$1]++} else {ips[$1]=1}} END {for (ip in ips) { print ips[ip], ip}}' "$ACCESSLOG" | sort -nk1

真实0m0.019s

用户0m0.004s

sys 0m0.008s

而你的重构命令:

awk '{ips[$1]++} END {for (ip in ips) { print ips[ip], ip}}' "${ACCESSLOG}" | sort -nk1

真实0m0.014s

用户0m0.004s

sys 0m0.012s

有趣的是比较速度......