1. 題目
有日誌 1.log,部分內容如下:
112.111.12.248 - [25/Sep/2013:16:08:31 +0800]formula-x.haotui.com "/seccode.php?update=0.5593110133088248" 200"http://formula-x.haotui.com/registerbbs.php" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;)"
61.147.76.51 - [25/Sep/2013:16:08:31 +0800]xyzdiy.5d6d.com "/attachment.php?aid=4554&k=9ce51e2c376bc861603c7689d97c04a1&t=1334564048&fid=9&sid=zgohwYoLZq2qPW233ZIRsJiUeu22XqE8f49jY9mouRSoE71" 301"http://xyzdiy.×××thread-1435-1-23.html" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"
請統計出每個IP的訪問量是多少?
2. 題目分析
根據日誌內容,可以看到IP地址就是第一段的內容,所以只需把1.log的第一段給過濾出來,然後進一步統計每個IP的數量即可。
過濾第一段,使用awk就可以了,而統計每個IP的訪問量則需要排序然後再計算數量,排序使用sort命令,統計每個IP的訪問量用uniq。
3. 具體shell命令
這道題,用shell腳本一條命令就足夠了:
awk '{print $1}' 1.log | sort -n | uniq -c | sort -n
解釋:
- awk 命令在分段方面比較有優勢,這裏的{print $1}將第一段打印出來,awk可以用-F指定分隔符,如果不指定分隔符,默認就以空白字符(比如空格、tab等),本題中,IP地址就是第一段。
- sort 命令就是排序,-n選項表示以數字的形式排序。如果不加-n,則以ASCII排序,本題的IP地址用數字的形式排序更易區分。
- uniq 命令用來去重複,一個文本如果有多行內容是一模一樣的,就使用uniq命令將相同的內容刪除,只保留一行。-c選項作用是計算重複的行數。所以,uniq -c 的作用正好就統計了ip的訪問量。不過,要注意,uniq去重要在排序之後進行。
- 最後的sort -n意思是按訪問量大小來排序,請求量越大的ip排在越後面。如果加一個-r選項,sort -nr,就是倒序排序。
4. 結語
這道題目還有另一種解法,明天再更新吧。
補充於4月11日
由於這篇文章在題目的例子裏有一些IP連接,所以每次修改發文官方都要重新審覈一天,我就不重新再寫一篇文章來寫另一種方法了。
這種方法最主要的區別,就是使用了awk的數組來統計結果,請看命令:
awk '{sum[$1]+=1};END{ for( a in sum)print (sum[a], a)}' 1.log | sort -nr | head -n 5
解釋一下,這條命令中$1 就表示日誌中的IP地址,用IP地址作爲數組的下標,每發現一個相同的IP地址,就統計數量加1;當awk遍歷日誌文件1.log 完畢,再循環輸出數組 sum 的結果,要注意數組的下標是 ip地址。
後面的 head -n 5 是爲了輸出出現訪問次數最高的5個訪問ip地址。