一、awk基本用法
1.1 awk概述
awk是一个编程语言/数据处理引擎。基于模式匹配检查输入文本,逐行处理并输出。
1.1.1 记录
记录:awk把每一个以换行符结束的行称为一个记录。
记录分隔符:默认的输入和输出的分隔符都是回车,保存在内建变量ORS和RS中。
1.1.2 域
记录中每个单词称做“域”,默认情况下以空格或tab分隔。awk可跟踪域的个数,并在内建变量NF中保存该值。如$ awk '{print $1,$3}' test将打印test文件中第一和第三个以空格分开的列(域)。
1.1.3 pattern { action statements }
awk的基本模式是 pattern { action statements },action部分是可以省略的,缺省情况下是输出,即{print $0},至于pattern可以理解成是表达式,通过pattern表达式的值的真假,来确定是否要进行action。比如1,最简单的awk用来实现cat的功能就是 awk '1',这边1就是pattern,当然,1也可以是2,3,4,5等其他数字,但如果用字母的话,就不行,因为字母会解释成变量,变量初始值未定义,初始值为假,或者可以加个!反义
1.2 命令格式
awk [选项] '[条件]{编辑指令}' 文件
前置命令 | awk [选项] '[条件]{编辑指令1};{编辑指令2}'
选项:F,v
条件:/正则/,数值/字符串比较,逻辑比较,运算符,BEGIN,END
编辑指令:print [变量],[常量]
变量:$n,$0,NF,NR 常量:必须以""括起来
1.3 选项
1.3.1 awk -F
指定分隔符,可省略(默认空格和tab位)
内建变量FS保存输入域分隔符的值,默认是空格或tab。可以同时使用多个域分隔符,这时应该把分隔符写成放到方括号中,如$awk -F'[:\t]' '{print $1,$3}' test,表示以空格、冒号和tab作为分隔符。
输出域的分隔符默认是一个空格,保存在OFS中。如$ awk -F: '{print $1,$5}' test,$1和$5间的逗号就是OFS的值。
1.3.2 awk -v var=val
调用外部shell变量
a=1000
awk -v var=$a 'BEGIN {print var}'
1.4 内置变量
变量 用途
FS 保存或设置字段分隔符,例如FS=":"
$n 指定分割的第n个字段,如$1、$3分别表示第1、第3列
$0 当前读入的整行文本内容
NF 记录当前处理行的字段个数(列数)
NR 记录当前已读入行的数量(行数)
FNR 保存当前处理行在原文本内的序号(行号)
FILENAME 保存 awk 当前处理的(文件名)
1.5 条件
1.5.1 BEGIN{}
BEGIN模块后紧跟着动作块,这个动作块在awk处理任何输入文件之前执行。所以它可以在没有任何输入的情况下进行测试。它通常用来改变内建变量的值,如OFS,RS和FS等,以及打印标题。如:$ awk 'BEGIN{FS=":"; OFS="\t"; ORS="\n\n"}{print $1,$2,$3}' test。上式表示,在处理输入文件以前,域分隔符(FS)被设为冒号,输出文件分隔符(OFS)被设置为制表符,输出记录分隔符(ORS)被设置为两个换行符。$ awk 'BEGIN{print "TITLE TEST"}只打印标题。
1.5.2 END{}
END不匹配任何的输入文件,但是执行动作块中的所有动作,它在整个输入文件处理完成后被执行。如$awk 'END{print "The number of records is" NR}' test,上式将打印所有被处理的记录数。
1.5.3 {}
在读取文件中执行n次。默认就是这个条件
这三种条件可以单独使用,也可以组合使用
1.5.4 匹配操作符
用来在记录或者域内匹配正则表达式
~表示列匹配
!~表示对列匹配取反
awk -F: '$0 ~/^root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
#在一整行中以root开头
awk -F: '$0 ~/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
#在一整行中有root即可
1.5.5 数值和字符串比较
==等于 !=不等于
>= < <=
1.5.6 逻辑比较
&& ||
awk '$3>=9&&$3<=10' log#找出9:00-10:00的日志信息1.5.7 运算符
- / % 普通加减乘除
++ -- 自加自减,放在变量前后的意义有重要区别
++var 先给var赋值,再对var进行累加
var++ 先使用var变量的值,再对var进行累加
!a[$0]++
这个要从awk的执行模式开始说,最后结合++运算符,和hash特色
patten分析:
1.使用了一个hash数组a
2.这个数组a,又是使用$0这个变量作为下标,即文件的每行值
3.当a[$0]未声明(udef)时,a[$0]为假。但是在未声明的情况下,进行一次a[$0]++后,a[$0]即为真
4.! 取反的优先级高于++
awk的基本模式是 ,pattern { action statements },action部分是可以省略的,缺省情况下是输出,即{print $0},至于pattern可以理解成是表达式,通过pattern表达式的值的真假,来确定是否要进行action
结论:当相同的行第一次读入时,pattern为真,行输出,再次读入后,patten为假,行乎略。所以!a[$0]++可以去除一行中重复的记录,以记录作为数组(可以将a理解为数组)索引
a[$1]++
和上面的表达式同理,可以根据记录中某个域删除这个域相同的记录,也可以根据这个域相同,执行另外一些相应的操作
+= -= *= /=
awk 'BEGIN{x=3;y=4;print x+y}'
awk 'BEGIN{x=2;print x+y}'#就算y变量没定义,也可以直接用,默认值为0二、awk高级应用
2.1 if指令
必须放在{}里面才行
2.1.1 if(条件){指令}
if单分支指令
2.1.2 if(条件){指令1}else{指令2}
if双分支指令
2.1.3 if(条件){指令1}else if (条件){指令2}
if多分支指令
统计普通用户有几个?系统用户有几个?
awk -F: '{if($3 < 1000){x++}else{y++}}END{print "normal users:"x,"super users:"y}' /etc/passwd
if($3 < 1000){x++}else{y++}
END{print x,y}2.2 while指令
while(条件){指令}
2.3 for指令
for(条件){指令}
2.4 awk数组定义
awk 'BEGIN{a[xx]=11;a[yy]=22;print a[xx],a[yy]}'
awk支持数组直接调用数组元素,而不是用0,1,2数字来调用
示例:
统计httpd_access_log的访问人数
准备工作:
使用ab软件模拟100个人访问,每个人100000次点击,生成access_log
ab -c 100 -n 10000 http://192.168.4.7/
指令:
awk '{ip[$1]++}END{for (i in ip){print i,ip[i]}}' /var/log/httpd/access_log |awk '$2>500{print $1}'
指令分解分析:
ip[$1]是一个数组变量,下标为$1。$1也是变量,是读取的文件的第一列
ip[$1]++
第一次读到ip[4.2]++,由于ip[4.2]不存在,首先赋值为0,再自加1,因此得到的值ip[4.2]=1
第二次读到ip[4.2],由于ip[4.2]已存在,使用原有值=1,再自加1,因此得到的值ip[4.2]=2
以此类推
for (i in ip){print i,ip[i]}是一个for循环,小括号里面是判断条件。i的值是ip这个数组的所有元素,即i in 4.2 4.5。
打印出来的结果
$1 $2
4.2 2
4.5 1
管道后的awk是用来判断异常情况并输出,$2>500的项就打印$1出来2.5 例子
2.5.1 显示网卡流量
ifconfig eth0|awk '/RX p/{print $5}'
2.5.2获取eth0的ip地址
ifconfig eth0 |awk -F '[ :]+' 'NR==2 {print $4}'
2.5.3 显示100以内可以被7整除或者包含7的数字
seq 100|awk '$1%7==0||$1~/7/'
2.5.4 统计/etc/passwd文件中出现多少次'root'
awk -F [:/] '{i=1}{while(i<=NF){if($i~/root/){j++};i++} }END{print j}' /etc/passwd
awk是逐行读入文本
读入第一行的时候:
初始i=1,$1==root,条件匹配j++=1 i++=1; $3=root,条件匹配j++=2 i++=2
读入第二行的时候
when i=2 so no $ equal root then j=2 after i=3
when i=3 so $1 equal root then j=3 after i=4- 本文转自 goldwinner 51CTO博客,原文链接:http://blog.51cto.com/355665/2071221,如需转载请自行联系原作者