Linux中对文本分组统计排序

场景

有时候需要对一些日志进行分组统计排序,比如统计下nginx日志昨天的QPS是多少

原理

分析文本,取出目标信息,可以用cut,在进行分组统计,可以用awk,最后排序,可以用sort

实战

nginx access日志长下面这样

192.168.1.100 - - [13/Jan/2021:00:05:11 +0800] "POST /app/images/logo.png HTTP/1.1" 200 3430 "-" "Jakarta Commons-HttpClient/3.1" "-"   "0.106"   "0.106"  "192.168.1.105:8080"
192.168.1.100 - - [13/Jan/2021:00:05:11 +0800] "POST /app/images/logo.png HTTP/1.1" 200 3430 "-" "Jakarta Commons-HttpClient/3.1" "-"   "0.106"   "0.106"  "192.168.1.105:8080"

分析一下:要统计QPS,只要把时间13/Jan/2021:00:05:11取出来分组统计就可以了

取时间cut

用cut命令,-c20-39意思是从第23取到39,不知道具体是多少就要个测,前面最好加一个head -n 10表示取首10行,否则日志太大终端直接卡死

head -n 10 access_bak_2021-01-13.log| cut -c20-39

13/Jan/2021:00:05:11
13/Jan/2021:00:05:11
13/Jan/2021:00:05:11
13/Jan/2021:00:05:14
13/Jan/2021:00:05:14
13/Jan/2021:00:05:14
13/Jan/2021:00:05:15
13/Jan/2021:00:05:15
13/Jan/2021:00:05:15
13/Jan/2021:00:05:15

分组统计awk

a[$1]+=1表示对第一列而言,遇到一样的就加一个1,反正对于只有一列的分组统计来说直接加后面这一坨就对了:awk '{a[$1]+=1}END{for (i in a)print i,a[i]}'

head -n 10 access_bak_2021-01-13.log| cut -c20-39 | awk '{a[$1]+=1}END{for (i in a)print i,a[i]}'

13/Jan/2021:00:05:11 3
13/Jan/2021:00:05:14 3
13/Jan/2021:00:05:15 4

到这里其实统计效果已经出来了

排序sort

sort命令中

  • -n表示以数值计算,否则sort会认为2比10大,因为2比1大嘛,这是sort的一贯作风
  • -r表示逆序,不加表示顺序
  • -k2表示以第2列来排序
    当然你也可以写成-nrk2,所以最后就是下面这种效果
head -n 10 access_bak_2021-01-13.log| cut -c20-39 | awk '{a[$1]+=1}END{for (i in a)print i,a[i]}' | sort -n -r -k2

13/Jan/2021:00:05:15 4
13/Jan/2021:00:05:14 3
13/Jan/2021:00:05:11 3

后记

实际中可能是这样的,后面加个| more当数据太多的时候使用

cat access_bak_2021-01-13.log| cut -c20-39 | awk '{a[$1]+=1}END{for (i in a)print i,a[i]}' | sort -n -r -k2 | more

也可能是这样的,最前面加一个grep用于最基本的筛选,比如你的nginx中多个应用或者你仅仅想统计某个path的时候

grep 'app' access_bak_2021-01-13.log| cut -c20-39 | awk '{a[$1]+=1}END{for (i in a)print i,a[i]}' | sort -n -r -k2 | more
上一篇:绘图的基本元素(ggplot2实现)


下一篇:使用RNN进行中文文本分类(酒店评论)