1.简单实例
awk逐行扫描文件,从第一行到最后一行,寻找匹配特定模式的行,并在这些行上进行你想要的操作
awk基本结构包括模式匹配(用于找到要处理的行)和处理过程(即处理动作)。 pattern {action}
行为用{}包括住,awk后面的模式加操作用单引号包括。
[nxuser@PSBJ-0-0-0 pstests]$ cat /etc/sysconfig/networkNETWORKING=yesHOSTNAME=PSBJ-0-0-0NOZEROCONF=yesNETWORKING_IPV6=yesIPV6_AUTOCONF=noGATEWAY=135.252.172.1备注:打印包含主机名的行,因为没有指定动作指令,默认动作为打印。[nxuser@PSBJ-0-0-0 pstests]$ awk '/HOSTNAME/' /etc/sysconfig/networkHOSTNAME=PSBJ-0-0-0[nxuser@PSBJ-0-0-0 pstests]$ awk '/HOSTNAME/ {print "find it!"}' /etc/sysconfig/networkfind it!
也可以写好awk命令的shell脚本,然后利用-f参数调用 ,如下所示
[nxuser@PSBJ-0-0-0 pstests]$ cat findhostname.sh /HOSTNAME/ {print "find it!"}//注意去掉单引号,否则报错[nxuser@PSBJ-0-0-0 pstests]$ awk -f findhostname.sh /etc/sysconfig/networkfind it!
2.基本操作
1,。awk一次从文件中读取一条记录,并将记录存储在字段变量$0中。记录被分割为字段并存储在$1,$2 ..., $NF中(默认使用空格或制表符为分隔符)。
内建变量NF为记录的字段个数,此处[nxuser@PSBJ-0-0-0 pstests]$ echo hello world |awk '{print $1,$2}'hello world [nxuser@PSBJ-0-0-0 pstests]$ echo hello world |awk '{print NF}'2[nxuser@PSBJ-0-0-0 pstests]$ echo hello world |awk '{print $NF}'world
2. 默认awk读取数据以空格或制表符作为分隔符,但可以通过-F或FS(field separator)变量来改变分隔符。
示例:awk -F 分隔符 '{print $1}'
或者 awk 'BEGIN {FS=":"} {print $1}'
[nxuser@PSBJ-0-0-0 pstests]$ echo hello:world |awk -F: '{print $1}'hello[nxuser@PSBJ-0-0-0 pstests]$ echo hello:world |awk 'BEGIN {FS=":"} {print $1}'hello
多个分隔符,利用 {FS="[:,]"}表示,如下
[nxuser@PSBJ-0-0-0 pstests]$ echo hello:world,ok |awk 'BEGIN {FS="[:,]"} {print $1,$2,$3}'hello world ok
3. 内置变量
以下为awk内置变量:
ARGC 命令行参数个数 FILENAME 当前输入文档的名称 FNR 当前输入文档的当前记录编号,尤其当有多个输入文档时有用 NR 输入流的当前记录编号 NF 当前记录的字段个数 FS 字段分隔符 OFS 输出字段分隔符,默认为空格 ORS 输出记录分隔符,默认为换行符\n RS 输入记录分隔符,默认为换行符\n
[nxuser@PSBJ-0-0-0 tmp]$ awk '{print FILENAME}' testfunction.sh testfunction.shtestfunction.shtestfunction.shtestfunction.shtestfunction.shtestfunction.shtestfunction.shtestfunction.shtestfunction.shtestfunction.shtestfunction.sh
[nxuser@PSBJ-0-0-0 tmp]$ awk '/HOSTNAME/' /etc/sysconfig/networkHOSTNAME=PSBJ-0-0-0[nxuser@PSBJ-0-0-0 tmp]$ awk '/HOSTNAME/ {print $1}' /etc/sysconfig/networkHOSTNAME=PSBJ-0-0-0[nxuser@PSBJ-0-0-0 tmp]$ awk -F= '/HOSTNAME/ {print $1}' /etc/sysconfig/networkHOSTNAME[nxuser@PSBJ-0-0-0 tmp]$
4. 表达式与操作符
表达式是由变量、常量、函数、正则表达式、操作符组成,awk中变量有字符变量和数字变量。如果在awk中定义的变量没有初始化,则初始值为空字串或0。
注意:字符操作时一定记得需要加引号 1) 变量定义示例: a="welcome to beijing" b=12 2) 操作符(awk操作符与C语言类似) + 加 - 减 * 乘 / 除 % 取余 ^ 幂运算 ++ 自加1 -- 自减1 += 相加后赋值给变量(x+=9等同于x=x+9) -= 相减后赋值给变量(x-=9等同于x=x-9) *= 相乘后赋值给变量(x*=9等同于x=x*9) /= 相除后赋值给变量(x/=9等同于x=x/9) > 大于 < 小于 >= 大于等于 <= 小于等于 == 等于 != 不等于 ~ 匹配 !~ 不匹配 && 与 || 或-F 指定分隔符,有END最后输出统计结果,否则输出每行的结果
[nxuser@PSBJ-0-0-0 tmp]$ awk '/aaaa/ {x+=1} END {print x}' test.txt
[nxuser@PSBJ-0-0-0 tmp]$ cat test.txtaaaabbbbccccddddaaaabbbbccccdddd[nxuser@PSBJ-0-0-0 tmp]$ awk '/aaaa/ {print x+=1}' test.txt 12[nxuser@PSBJ-0-0-0 tmp]$ awk '/aaaa/ {x+=1} END {print x}' test.txt 2[nxuser@PSBJ-0-0-0 tmp]$ awk -F: '$3>500 {print $1}' /etc/passwd
5 循环
1. {if(xxx) print xxx ; else xxx}以分号分隔
[nxuser@PSBJ-0-0-0 tmp]$ cat /etc/passwd |grep mysql | awk -F: '{if($3>100) print $3; else print "too small"}'31034
2. for 循环
[nxuser@PSBJ-0-0-0 tmp]$ awk 'BEGIN {for(i=1;i<=10;i++) print i}' test.txt12345678910[nxuser@PSBJ-0-0-0 tmp]$ awk '{for(i=1;i<=10;i++) print i}' test.txt1234567891012345678910123456789101234567891012345678910123456789101234567891012345678910[nxuser@PSBJ-0-0-0 tmp]$ vi test.txt aaaabbbbccccddddaaaabbbbccccdddd
3. while循环
[nxuser@PSBJ-0-0-0 tmp]$ awk 'BEGIN { while (i<=10) {++i; print i}}' 1234567891011
6 应用场景
使用 awk 场景举例
统计浏览器类型
如果我们想知道那些类型的浏览器访问过网站,并按出现的次数倒序排列,我可以使用下面的命令:
awk -F\" '{print $6}' access.log | sort | uniq -c | sort -fr |
[nxuser@PSBJ-0-0-0 tmp]$ cat assess.log nxuser:firefox:201304001root:IE:201304001nxuser:firefox:201304001root:IE:201304001root:IE:201304001nxuser:firefox:201304001nxuser:firefox:201304001root:IE:201304001root:IE:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001root:IE:201304001root:IE:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001root:IE:201304001nxuser:firefox:201304001nxuser:firefox:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001
比如上述是访问log,按统计浏览器类型统计次数,如下
-c 参数显示文件中每行连续出现的次数。所以先用sort排序,然后用uniq -c 统计次数。如果不用sort,不能实现统计。因为uniq是统计每行连续出现的次数
uniq命令不加任何参数,仅显示连续重复的行一次
[nxuser@PSBJ-0-0-0 tmp]$ awk -F: '{print $2}' assess.log |sort | uniq -c 13 IE 12 firefox [nxuser@PSBJ-0-0-0 tmp]$ awk -F: '{print $2}' assess.log |sort | uniq IEfirefox
备注:
sort命令是帮我们依据不同的数据类型进行排序,其语法及常用参数格式:
sort [-bcfMnrtk][源文件][-o 输出文件] 补充说明:sort可针对文本文件的内容,以行为单位来排序。参 数:
-b 忽略每行前面开始出的空格字符。 -c 检查文件是否已经按照顺序排序。 -f 排序时,忽略大小写字母。 -M 将前面3个字母依照月份的缩写进行排序。 -n 依照数值的大小排序。 -o<输出文件> 将排序后的结果存入指定的文件。 -r 以相反的顺序来排序。 -t<分隔字符> 指定排序时所用的栏位分隔字符。 -k 选择以哪个区间进行排序。7 测试sort命令
sort -u 去除重复 ,如下:
[nxuser@PSBJ-0-0-0 tmp]$ sort -u assess.log nxuser:firefox:201304001root:IE:201304001
不带任何参数,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出
[nxuser@PSBJ-0-0-0 tmp]$ sort assess.log nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001
sort -r sort默认的排序方式是升序,如果想改成降序,就加个-r就搞定了
[nxuser@PSBJ-0-0-0 tmp]$ sort -r assess.log root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001root:IE:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001nxuser:firefox:201304001
http://manual.blog.51cto.com/3300438/932958