awk命令分析日志的简单笔记

awk是一个文本分析工具,可以用来进行流量日志分析

之前无意中看到了这个命令,简单记一下笔记 ,在打线下的时候可能会有用

awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk。

 

有三种方式调用awk

1.命令行方式
awk [options]  'script'  filename
其中,script 是真正awk命令,[-F域分隔符]是可选的。filename 是待处理的文件。
在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。
2.shell脚本方式
将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。
相当于shell脚本首行的:#!/bin/sh
可以换成:#!/bin/awk

3.将所有的awk命令插入一个单独文件,然后调用:
awk -f scriptfile   filename
其中,-f选项加载awk-script-file中的awk脚本

options 是命令选项 -- 比如几个常用命令选项

  -F xx  以xx为分隔符,awk的默认分隔符为空格   例如 -F ':' 这样

  -f scriptfile  从脚本文件中读取awk命令  这时候就不需要后面的'script'了 

  -v var=value   赋值一个用户定义变量,将外部变量传递给awk

script  则是如何对文本进行处理,支持正则表达式/xxx/,关系表达式即字符串或数字的比较测试,模式匹配表达式--用运算符~(匹配)和~!(不匹配)

  以及     BEGIN{ commands } pattern{ commands } END{ commands } 这三种语句块

  BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。

  END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。

  pattern语句块中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块。

filenames则是要处理的文件名,可以用 |  将之前命令的输出直接用awk处理,就不需要filenames了,也可以将wak的输出通过 |  让head和tail命令来处理

 

 

内置变量

说明:[A][N][P][G]表示第一个支持变量的工具,[A]=awk、[N]=nawk、[P]=POSIXawk、[G]=gawk

$n 当前记录的第n个字段,比如n为1表示第一个字段,n为2表示第二个字段。  
$0 这个变量包含执行过程中当前行的文本内容。  
[N] ARGC 命令行参数的数目。  
[G] ARGIND 命令行中当前文件的位置(从0开始算)。  
[N] ARGV 包含命令行参数的数组。  
[G] CONVFMT 数字转换格式(默认值为%.6g)。  
[P] ENVIRON 环境变量关联数组。  
[N] ERRNO 最后一个系统错误的描述。  
[G] FIELDWIDTHS 字段宽度列表(用空格键分隔)。  
[A] FILENAME 当前输入文件的名。  
[P] FNR 同NR,但相对于当前文件。  
[A] FS 字段分隔符(默认是任何空格)。  
[G] IGNORECASE 如果为真,则进行忽略大小写的匹配。  
[A] NF 表示字段数,在执行过程中对应于当前的字段数。  
[A] NR 表示记录数,在执行过程中对应于当前的行号。  
[A] OFMT 数字的输出格式(默认值是%.6g)。  
[A] OFS 输出字段分隔符(默认值是一个空格)。  
[A] ORS 输出记录分隔符(默认值是一个换行符)。  
[A] RS 记录分隔符(默认是一个换行符)。  
[N] RSTART 由match函数所匹配的字符串的第一个位置。  
[N] RLENGTH 由match函数所匹配的字符串的长度。  
[N] SUBSEP 数组下标分隔符(默认值是34)。

 

输出函数

awk中同时提供了print和printf两种打印输出的函数。

其中print函数的参数可以是变量、数值或者字符串。字符串必须用双引号引用,参数用逗号分隔。如果没有逗号,参数就串联在一起而无法区分。这里,逗号的作用与输出文件的分隔符的作用是一样的,只是后者是空格而已。

printf函数,其用法和c语言中printf基本相似,可以格式化字符串,输出复杂时,printf更加好用,代码更易懂

 

简单函数用法

打开外部文件 close函数

awk 'BEGIN{while("cat /etc/passwd"|getline){print $0;};close("/etc/passwd");}'  

逐行读取外部文件内容 getline

awk 'BEGIN{while(getline < "/etc/passwd"){print $0;};close("/etc/passwd");}'  

调用外部应用程序 system函数

awk 'BEGIN{b=system("ls -al");print b;}'

 

字符串操作

查找字符串  index函数

awk 'BEGIN{info="this is a test2010test!";print index(info,"test")?"ok":"no found";}'  

正则表达式查找匹配

awk 'BEGIN{info="this is a test2010test!";print match(info,/[0-9]+/)?"ok":"no found";}'  

字符串截取

awk 'BEGIN{info="this is a test2010test!";print substr(info,4,10);}'  

字符串分割

awk 'BEGIN{info="this is a test";split(info,tA," ");print length(tA);for(k in tA){print k,tA[k];}}'  

 


 

去实验吧随便找了个日志的题目 然后拿日志过来试一试

不知道为什么突然上传不了图片了只有贴一下数据 简单测试一下

root@ubuntu:~# cat log | head -10
192.168.1.2 - - [16/Dec/2010:01:21:10 +0800] "GET / HTTP/1.1" 302 -
192.168.1.2 - - [16/Dec/2010:01:21:10 +0800] "GET /xampp/ HTTP/1.1" 302 -
192.168.1.2 - - [16/Dec/2010:01:21:10 +0800] "GET /xampp/splash.php HTTP/1.1" 200 1321
192.168.1.2 - - [16/Dec/2010:01:21:10 +0800] "GET /xampp/xampp.css HTTP/1.1" 200 3991
192.168.1.2 - - [16/Dec/2010:01:21:10 +0800] "GET /xampp/img/blank.gif HTTP/1.1" 200 43
192.168.1.2 - - [16/Dec/2010:01:21:10 +0800] "GET /xampp/img/xampp-logo.jpg HTTP/1.1" 200 19738
192.168.1.2 - - [16/Dec/2010:01:21:44 +0800] "GET /xampp/lang.php?zh HTTP/1.1" 302 -
192.168.1.2 - - [16/Dec/2010:01:21:44 +0800] "GET /xampp/index.php HTTP/1.1" 200 589
192.168.1.2 - - [16/Dec/2010:01:21:44 +0800] "GET /xampp/head.php HTTP/1.1" 200 1362
192.168.1.2 - - [16/Dec/2010:01:21:44 +0800] "GET /xampp/start.php HTTP/1.1" 200 534

 用 / 分割 输出第一部分

root@ubuntu:~# awk -F '/'  '{print $1}' log | head -10
192.168.1.2 - - [16
192.168.1.2 - - [16
192.168.1.2 - - [16
192.168.1.2 - - [16
192.168.1.2 - - [16
192.168.1.2 - - [16
192.168.1.2 - - [16
192.168.1.2 - - [16
192.168.1.2 - - [16
192.168.1.2 - - [16

用-分割 输出第一部分和最后一部分

root@ubuntu:~# awk -F '-'  '{print $1,$NF}' log | head -10
192.168.1.2  
192.168.1.2  
192.168.1.2   [16/Dec/2010:01:21:10 +0800] "GET /xampp/splash.php HTTP/1.1" 200 1321
192.168.1.2   [16/Dec/2010:01:21:10 +0800] "GET /xampp/xampp.css HTTP/1.1" 200 3991
192.168.1.2   [16/Dec/2010:01:21:10 +0800] "GET /xampp/img/blank.gif HTTP/1.1" 200 43
192.168.1.2  logo.jpg HTTP/1.1" 200 19738
192.168.1.2  
192.168.1.2   [16/Dec/2010:01:21:44 +0800] "GET /xampp/index.php HTTP/1.1" 200 589
192.168.1.2   [16/Dec/2010:01:21:44 +0800] "GET /xampp/head.php HTTP/1.1" 200 1362
192.168.1.2   [16/Dec/2010:01:21:44 +0800] "GET /xampp/start.php HTTP/1.1" 200 534

统计总行数

root@ubuntu:~# awk  'BEGIN{x=0;} {x++;} END{print x}' log 
929
root@ubuntu:~# wc -l log
929 log

用/分割  把输出的最后两个部分写进looog文件中

root@ubuntu:~# awk -F '/'  '{print $(NF-1),$NF}' log > looog
awk: cmd. line:1: (FILENAME=log FNR=929) fatal: attempt to access field -1

root@ubuntu:~# cat looog | tail -10 pixel.gif HTTP 1.1" 404 1337 admin HTTP 1.1" 403 1110 login.php HTTP 1.1" 403 1110 robots.txt HTTP 1.1" 200 264 admin.php HTTP 1.1" 200 3763 pixel.gif HTTP 1.1" 404 1279 pixel.gif HTTP 1.1" 404 1279 admin.php HTTP 1.1" 200 3762 pixel.gif HTTP 1.1" 404 1279 pixel.gif HTTP 1.1" 404 1279

 

查找最后20行内有没有 'php'   不用三元表达式就会直接返回位置

root@ubuntu:~# awk '{print index($0,"php")?"find":"no"}' log | tail -20
no
no
no
no
no
find
find
find
no
no
no
find
no
find
no
no
find
no
no
no

用正则查找

root@ubuntu:~# awk '{print match($0,"php")?"find":"no"}' log | tail -20
no
no
no
no
no
find
find
find
no
no
no
find
no
find
no
no
find
no
no
no

截取前五个字符

root@ubuntu:~# awk '{print substr($0,5,5)}' log | tail -10
168.1
168.1
168.1
168.1
168.1
168.1
168.1
168.1
168.1

 

 

参考资料

https://blog.csdn.net/u011204847/article/details/51205031

https://www.cnblogs.com/lyftest/p/7373453.html

http://www.cnblogs.com/ggjucheng/archive/2013/01/13/2858470.html

posted @ 2018-04-09 20:41  slpawn  阅读(3387)  评论(0编辑  收藏  举报