这里写目录标题
一,统计日志中各IP访问不同状态码的次数
1,生成200状态码的次数
命令:
awk '$9==200{arr[$1]++}END{for(i in arr){print arr[i], i}}' access.log
结果
2,生成非200状态码的次数并降序排
awk '$9!=200{arr[$1]++}END{for(i in arr){print arr[i], i}}' access.log | sort nr
结果
3,使用awk排序函数
代码实现
$9!=200{arr[$1]++}
END{
PROCINFO["sorted_in"]="@val_num_desc";
for(i in arr){
if(cnt++==10){exit}
print arr[i],i
}
}
结果
二,统计独立IP
统计每个URL的独立访问IP有多少个(去重),并且要为每个URL保存一个对应的文件
代码实现
BEGIN{
FS="|"
}
!arr[$1,$2]++{
arr1[$1]++
}
END{
for(i in arr1){
print i, arr1[i] > (i".txt")
}
}
结果
三,处理缺失数据
在缺失的这部分用传统的awk打印第6列因存在空格会失败,当用重构时依旧缺失
使用如下命令则会成功
awk '{print $0}' FIELDWIDTHS="2 2:6 2:6 2:3 2:13 2:11" demo2.txt
使用FIELDWIDTHS,每列中最大宽度,如2:6是两个空格及第二列最大宽度为6
四,处理字段中包含了字段分隔符的数据
Robbins,Arnold,“1234 A Pretty Street,
NE”,MyTown,MyState,12345-6789,USA取得第三个字段"1234 A Pretty Street, NE"
使用命令
cat demo3.txt | awk 'BEGIN{FPAT="[^,]+|\".*\""}{print $1,$3}'
FPAT可以收集正则匹配的结果,并将它们保存在各个字段中
[^,]+表示除了,之外所有字符,即Robbins保存在$1中,再除去,将Arnold保存在$2中,如此这样以此列推。如
五,筛选给定时间范围内的日志
思路:把时间转换成一个时间戳,再和目前时间作比较
awk提供了mktime()函数,它可以将时间转换成epoch时间值。可以取得日志中的时间字符串部分,再将它们的年、月、日、时、分、秒都取出来,然后放入mktime()构建成对应的epoch值。因为epoch值是数值,所以可以比较大小,从而决定时间的大小。
先做时间比对:选定什么时间的日志,如下:筛选2023年8月2日23时38分00秒之后
BEGIN{
# 要筛选什么时间的日志,将其时间构建成epoch值
which_time = mktime("2023 08 02 23 38 00")
}
{
# 取出日志中的日期时间字符串部分
match($0,"^.*\\[(.*)\\].*",arr)
# 将日期时间字符串转换为epoch值
tmp_time = strptime2(arr[1])
# 通过比较epoch值来比较时间大小
if(tmp_time > which_time){
print
}
}
# 构建的时间字符串格式为:"10/Nov/2019:23:53:44+08:00"
function strptime2(str,dt_str,arr,Y,M,D,H,m,S) {
dt_str = gensub("[/:+]"," ","g",str)
# dt_sr = "10 Nov 2019 23 53 44 08 00"
split(dt_str,arr," ")
Y=arr[3]
M=mon_map(arr[2])
D=arr[1]
H=arr[4]
m=arr[5]
S=arr[6]
return mktime(sprintf("%s %s %s %s %s %s",Y,M,D,H,m,S))
}
function mon_map(str,mons){
mons["Jan"]=1
mons["Feb"]=2
mons["Mar"]=3
mons["Apr"]=4
mons["May"]=5
mons["Jun"]=6
mons["Jul"]=7
mons["Aug"]=8
mons["Sep"]=9
mons["Oct"]=10
mons["Nov"]=11
mons["Dec"]=12
return mons[str]
}
结果