定义:
是一种样式扫描和处理语言。允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。
基本结构:
awk ‘{pattern + action}’ {filenames}
其中 pattern 模式 表示 AWK 在数据中查找的内容,而 action 操作 是在找到匹配内容时所执行的一系列命令。
两者是可选的,如果没有模式,则action应用到全部记录,如果没有action,则输出匹配全部记录。默认情况下,每一个输入行都是一条记录,但用户可通过RS变量指定不同的分隔符进行分隔。
模式
模式可以是以下任意一个:
/正则表达式/:使用通配符的扩展集。
关系表达式:可以用下面运算符表中的关系运算符进行操作,可以是字符串或数字的比较,如$2>$1选择第二个字段比第一个字段长的行。
模式匹配表达式:用运算符(匹配)和!(不匹配)。
模式,模式:指定一个行的范围。该语法不能包括BEGIN和END模式。
BEGIN:让用户指定在第一条输入记录被处理之前所发生的动作,通常可在这里设置全局变量。
END:让用户在最后一条输入记录被读取之后发生的动作。
操作
操作由一人或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内。主要有四部份:
变量或数组赋值
输出命令
内置函数
控制流命令
用途:
awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,
通常,awk是以文件的一行为处理单位的(\n)。awk每接收文件的一行,然后执行相应的命令,来处理文本。
工作流程:
先执行BEGIN,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域, 1 表 示 第 一 个 域 , 1表示第一个域, 1表示第一个域,n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。
使用方式:
1.命令行方式
awk [-F ‘field-separator’] ‘commands’ input-file(s)
其中,commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。
在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域 。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格或 “[tab]键”。
域分隔符可以写成正则方式:
例: 其中$3 表示取第3个域
awk -F ‘[ ,]+’ ‘{print $3" "$7}’ test.txt
2.shell脚本方式
将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。
相当于shell脚本首行的:#!/bin/sh
可以换成:#!/bin/awk
3.将所有的awk命令插入一个单独文件,然后调用
awk -f awk-script-file input-file(s)
其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的是一样的。
用法
1.搜索/etc/passwd有root关键字的所有行
awk -F: ‘/root/’ /etc/passwd
等价于: awk -F: ‘/root/{print $0}’ /etc/passwd
等价于
匹配了pattern(这里是root)的行才会执行action(没有指定action,默认输出每行的内容)
搜索支持正则,例如找root开头的: awk -F: ‘/^root/’ /etc/passwd
2.从筛选出的结果集中awk进行操作
上述命令等价于
less /etc/passwd | grep “root”|awk ‘{print $0}’
3.显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行添加列名name,shell,在最后一行添加"blue,/bin/nosh"
cat /etc/passwd |awk -F ‘:’ ‘BEGIN {print “name,shell”} {print $1","$7} END {print “blue,/bin/nosh”}’
4.显示查询工单耗时超过5000ms的查询总数
less /var/sankuai/logs/crmtask.log-2018-02-08-1.log | grep ‘查询工单 耗时,cost=’ | awk ‘{split($0,a,"=");if(a[2]>5000)count++} END {print " total is",count}’
这里没有初始化count,默认是0
awk内置变量
$n 当前记录的第n个字段,字段间由FS分隔。
$0 完整的输入记录。
ARGC 命令行参数的数目。
ARGIND 命令行中当前文件的位置(从0开始算)。
ARGV 包含命令行参数的数组。
CONVFMT 数字转换格式(默认值为%.6g)
ENVIRON 环境变量关联数组。
ERRNO 最后一个系统错误的描述。
FIELDWIDTHS 字段宽度列表(用空格键分隔)。
FILENAME 当前文件名。
FNR 同NR,但相对于当前文件。
FS 字段分隔符(默认是任何空格)。
IGNORECASE 如果为真,则进行忽略大小写的匹配。
NF 当前记录中的字段数。
NR 当前记录数。
OFMT 数字的输出格式(默认值是%.6g)。
OFS 输出字段分隔符(默认值是一个空格)。
ORS 输出记录分隔符(默认值是一个换行符)。
RLENGTH 由match函数所匹配的字符串的长度。
RS 记录分隔符(默认是一个换行符)。
RSTART 由match函数所匹配的字符串的第一个位置。
SUBSEP 数组下标分隔符(默认值是\034)。
例:
统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容
1.print,print函数的参数可以是变量、数值或者字符串。字符串必须用双引号引用,参数用逗号分隔。如果没有逗号,参数就串联在一起而无法区分。这里,逗号的作用与输出文件的分隔符的作用是一样的,只是后者是空格而已
awk -F ‘:’ ‘{print “filename:” FILENAME “,linenumber:” NR “,columns:” NF “,linecontent:”$0}’ /etc/passwd
2.printf,其用法和c语言中printf基本相似,可以格式化字符串,输出复杂时,printf更加好用,代码更易懂。
awk -F ‘:’ ‘{printf(“filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n”,FILENAME,NR,NF,$0)}’ /etc/passwd
注:
%-10s
%s表示字符串格式打印
-表示右对齐,10表示占10个字符空间,不足10个用空格代替
awk编程
action{}可以有多个语句,以;号隔开
条件语句
awk ‘{if ($1 <$2) print $2 “too high”}’ test。如果第一个域小于第二个域则打印。
awk ‘{if ($1 < $2) {count++; print “ok”}}’ test.如果第一个域小于第二个域,则count加一,并打印ok。
awk ‘{if ($1 > 100) print $1 “bad” ; else print “ok”}’ test。如果$1大于100则打印$1 bad,否则打印ok。
awk ‘{if ($1 > 100){ count++; print $1} else {count–; print $2}’ test。如果$1大于100,则count加一,并打印$1,否则count减一,并打印$1。
循环语句
awk有三种循环: while循环;for循环;special for循环。
while,for语句
awk ‘{ i = 1; while ( i <= NF ) { print NF,KaTeX parse error: Expected 'EOF', got '}' at position 7: i; i++}̲}' test。变量的初始值为…i}’ test。作用同上。
bread continue 语句
break用于在满足条件的情况下跳出循环;continue用于在满足条件的情况下忽略后面的语句,直接返回循环的顶端
{for ( x=3; x<=NF; x++)
if (KaTeX parse error: Expected 'EOF', got '}' at position 35: …d out!"; break}}̲ {for ( x=3; x<…x==0){print “Get next item”; continue}}
next 语句从输入文件中读取一行,然后从头开始执行awk脚本。如:
{if ($1 ~/test/){next}
else {print}
}
exit 语句用于结束awk程序,但不会略过END块。退出状态为0代表成功,非零值表示出错。
数组
awk中数组的下标可以是数字和字母,数组的下标通常被称为关键字(key)。值和关键字都存储在内部的一张针对key/value应用hash的表格里。由于hash不是顺序存储,因此在显示数组内容时会发现,它们并不是按照你预料的顺序显示出来的。数组和变量一样,都是在使用时自动创建的,awk也同样会自动判断其存储的是数字还是字符串。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。
例:
1.多行构成数组,显示/etc/passwd的账户
awk -F ‘:’ ‘BEGIN {count=0;} {name[count] = $1;count++} END{for (i = 0; i < NR; i++) print i, name[i]}’ /etc/passwd
2.读取文件中yitom开头的域,并组成数组,打印有值的数组元素。打印的顺序是随机的
$ awk ‘/^tom/{name[NR]=$1}; END{for(i in name){print name[i]}}’ test