awk命令
日期:2014-12-15 11:59:10
最后更新日期:2016-05-20 14:25:25
1.awk脚本由pattern-action和function组成。
pattern { action statements }
function name(parameter list) { statements }
其中pattern:
BEGIN
END
/regular expression/
relational expression
pattern && pattern
pattern || pattern
pattern ? pattern : pattern
(pattern)
! pattern
pattern1, pattern2
这里BEGIN和END也统一称为pattern。
awk执行过程如下,该段描述来源于awk的man手册的自我理解:
a.首先执行命令行中-v参数指定的变量赋值
b.awk执行BEGIN部分代码,然后读取命令行参数指定的数据文件,数据文件可以有多个,先后顺序为参数的顺序,没有指定数据文件时,默认为读取标准输入,若数据文件的的名字为var=val类型,则认为为变量赋值
c.以行为单位读取数据文件中的一条记录,若匹配了pattern,则执行action,当所有的记录全部处理完了,执行结束的END部分
2.awk变量和数组
awk提供了一些内置变量,awk定义用RS分割的为记录(record),FS分割的字段(field),$0表示该条记录,$1表示该记录的第一个字段,依次类推,$NS为最后一个字段,其他具体内置变量见awk手册。
所有未定义的变量值,数字为0,字符串为空字符串""。
变量类型
字段也是一个变量,变量的类型,可以认为是字符串类型或数值类型,由执行的操作决定,若与数字运算,那么为数值类型,若与字符串运算,那么为字符串类型。强制转换即为变量与0相加,那么该变量从此被认为是数字类型,变量与空字符串连接,那么该变量从此为字符串类型(不过强制转换的意义,感觉不大,本身是高级语言了,到最后计算时自动判断自动强制转换不更好)。
数组
awk将数组视为关联数组,并且支持多维数组,多维数组的下标为x[0,0]。
[code lang="cpp"]
BEGIN {AAA="hello";x[0,0]="A";x[0,1]="B";} /testa/ { print AAA,x[0,0],x[0,1] }
[/code]
判断key是否存在的in的关键字
[code lang="cpp"]
if (val in array)
print array[val]
[/code]
in语句还可以用于数组的遍历,数组中的某个元素也可以使用delete关键字删除,若没有指定下标,则删除整个数组。
3.操作符
选项 | 说明 |
(...) | Grouping |
$ | 字段引用,如$0,$1 |
++ -- | 自加,自减,前缀和后缀 |
^ | 幂操作符 |
+ - ! | 加,减,逻辑非 |
* / % | 乘,除,求余 |
+ - | 加减 |
space | 字符串连接 |
|和|& | 对于getline, print, and printf的管道io,网络io |
< >
<= >= != == | 关系操作符 |
~ !~ | 正则表达式的匹配,反向匹配 |
in | 数组的成员操作符 |
&& | 逻辑与 |
|| | 逻辑或 |
?: | c语言风格的条件语句 |
= += -= *= /= %= ^= | 赋值 |
4.控制符
if (condition) statement [ else statement ]
while (condition) statement
do statement while (condition)
for (expr1; expr2; expr3) statement
for (var in array) statement
break
continue
delete array[index]
delete array
exit [ expression ]
{ statements }
5.Special File Names
选项 | 说明 |
/dev/stdin | 标准输入 |
/dev/stdout | 标准输出,如:print "You blew it!" > "/dev/stderr" |
/dev/stderr | 标准错误输出 |
/dev/fd/n | 文件描述符n,如:print "You blew it!" | "cat 1>&2" |
/inet/tcp/lport/rhost/rport | tcp套接字,与|&操作符配合使用 |
/inet/udp/lport/rhost/rport | udp套接字 |
/inet/raw/lport/rhost/rport | 保留未将来使用 |
/dev/pid | 用户id等一系列类似文件 |
6.Numeric Functions
选项 | 说明 |
atan2(y, x) | 返回arctangent of y/x in radians |
cos(expr) | 余弦函数 |
exp(expr) | 幂函数 |
int(expr) | 取整函数 |
log(expr) | log函数 |
rand() | 随机函数 |
sin(expr) | 正弦函数 |
sqrt(expr) | 开方函数 |
srand([expr]) | 随机函数 |
7.String Functions
选项 | 说明 |
asort(s [, d]) | 将s根据value排序,如果存在d,则通过d返回 |
asorti(s [, d]) | 类似asort,不过排序是用数组的index |
gensub(r, s, h [, t]) | 正则表达式r在t中匹配,匹配了则用s替换,若t不存在则$0。 h如果为"g"或"G"则全局替换,为数字,则表示替换第h个。同时\N表示第N个匹配部分, 如:/test/ {tmp=gensub("test(.*)","\\1","g",$9);print $1,tmp; } |
gsub(r, s [, t]) | 正则表达式r在t中匹配,若t没有,则$0匹配 |
index(s, t) | 返回子串t在字符串s的位置 |
length([s]) | 返回字符串的长度 |
match(s, r [, a]) | 在s通过正则表达式r匹配,将位置通过a返回 |
split(s, a [, r]) | 根据正则表达式,将s分割到a中,若r不填,则FS分割 |
sprintf(fmt, expr-list) | 根据fmt返回打印字符串 |
strtonum(str) | 返回str代表的数字,若0开始,则为8进制,若0x开始,则为16进制 |
sub(r, s [, t]) | 等同gsub,不过仅替换第一个 |
substr(s, i [, n]) | 返回s的子串,从i开始的n个字符 |
tolower(str) | 返回str一个全部转换为小写的copy |
toupper(str) | 返回str一个全部转换为大写的copy |
8.awk一例:
感觉工作中,最容易浪费时间的,就是突然想测试某个东西,需要写个脚本,该脚本用bash shell或python实现,发现用到的某个命令或者实现某个功能的python代码不熟悉,然后查看man手册,python的则查看官方文档,短则十几分钟,长达半天。今后一定要改掉这个毛病,尽快用最捷径的方法实现好。可以网上查找别人实现的类似脚本,之前一直很鄙视随便网上找。学习得扎实,工作才能轻松。:)。例如今天本来需要写的一个脚本,PS:忘记awk这样用
[code lang="cpp"]
[root@23145 ~]# netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'
TIME_WAIT 57
CLOSE_WAIT 489
FIN_WAIT1 82
FIN_WAIT2 166
ESTABLISHED 8768
SYN_RECV 93
CLOSING 3
LAST_ACK 1
[/code]
9.awk
awk 'BEGIN{has=0;all++}{if( index($0, "foo") != 0) {has++;} if( index($0, "bar") != 0 ) {all++;} }END{print all,has}' ${file}`