异想天开

What's the true meaning of light, Could you tell me why

awk命令

日期:2014-12-15 11:59:10
  
最后更新日期:2016-05-20 14:25:25
awk是一门脚本语言的定义,pattern scanning and processing language,有规范的posix标准手册。实际linux系统经常是使用的是gnu实现的awk,linux系统的awk命令,常为gawk的软连接。
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/rporttcp套接字,与|&操作符配合使用
/inet/udp/lport/rhost/rportudp套接字
/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
其他函数见man手册。

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}`