awk高级编程

来源:互联网 发布:守望先锋的衰落 知乎 编辑:程序博客网 时间:2024/06/18 11:34

核心
学习AWK的高级编程

1、读取下一条记录
awk中next语句使用,在循环行匹配,如果遇到next,就会跳过当前行,直接忽略下面语句,而进行下一行匹配。next语句一般用于多行合并。当记录行号除以2余1,就跳过当前行,下面的print NR,$0也不会执行,下一行开始,程序有开始判断NR%2值。
这个时候记录行号:2,就会执行下面语句块 'print NR,$0'

[root@SZB-L0032013 awk]# cat file abcdef[root@SZB-L0032013 awk]# awk 'NR%2==1{next}{print NR,$0;}' file 2 b4 d6 f

分析发现需要将包含有web行进行跳过,然后需要将内容与下面行合并为一行

[root@SZB-L0032013 awk]# cat web web01 192.168.1.81mysqld okhttp oksemail okweb02 192.168.1.82mysql okhttp okweb03semail okhttp ok [root@SZB-L0032013 awk]# awk '/^web/{T=$0;next;}{print T": t" $0 }' web web01 192.168.1.81: tmysqld okweb01 192.168.1.81: thttp okweb01 192.168.1.81: tsemail okweb02 192.168.1.82: tmysql okweb02 192.168.1.82: thttp okweb03: tsemail okweb03: thttp ok 

2、读取一条记录
awk getline用法:输出重定向需用到getline函数,getline从标准输入、管道或者当前正在处理的文件之外的其他输入文件获得输入。它负责从输入获得下一行的内容,并给NF,NR和FNR等内建变量赋值,如果得到一条记录,getline函数返回1,如果到达文件的末尾就返回0,如果出现错误,例如文件打开失败,就返回-1,getline语法:getline var,变量var包含了特定行的内容

awk getline从整体上来说,用法说明
当其左右无重定向符|或<时: getline作用于当前文件,读入当前文件的第一行给其后跟的变量var或$0(无变量),应该注意到,由于awk在处理getline之前已经读入了一行,所以getline得到的返回结果是隔行的。
当其左右有重定向符|或<时: getline则作用于定向输入文件,由于该文件是刚打开,并没有被awk读入一行,只是getline读入,那么getline返回的是该文件的第一行,而不是隔行。

执行Linux的date命令,并通过管道输出给getline,然后再把输出赋值给自定义变量out,并打印它

[root@SZB-L0032013 awk]# awk 'BEGIN{"date"|getline out;print out}'Wed Mar 15 08:25:25 CST 2017

执行Linux的date命令,并通过管道输出给getline,然后getline从管道中读取并将输入赋值给out,
split函数把变量out转化成数组mon,然后打印数组mon的第二个元素

[root@SZB-L0032013 awk]# awk 'BEGIN{"date"|getline out;split(out,mon);print mon[2]}'Mar

命令ls的输出传递给getline作为输入,循环使getline从ls的输出中读取一行,并把它打印到屏幕,这里没有
输入文件,因为BEGIN块在打开输入文件前执行,所以可以忽略输入文件

[root@SZB-L0032013 awk]# awk 'BEGIN{ while( "ls" | getline) print }'awk.filefilelog.txtsorce.txtview.shweb

3、循环以及逻辑判断
if 判断
每条命令语句后面可以用;分号结尾

[root@SZB-L0032013 awk]# awk 'BEGIN{test=100 ;> if(test>90){> print "very good";> }> else if(test>60){> print "good";> }> else{> print "no pass"> }> }'very good

while循环

[root@SZB-L0032013 awk]# awk 'BEGIN{ > test=100;> total=0;> while(i<=test){> total+=i;> i++;> }> print total;}'5050

for循环
for循环有2种格式
1、
for(变量 in 数组)
{
语句
}
示例:

[root@SZB-L0032013 ~]# awk '> BEGIN{> for(k in ENVIRON) {> print k"="ENVIRON[k];> }> }'TERM=vt100G_BROKEN_FILENAMES=1SHLVL=1PWD=/rootTMOUT=1800HISTTIMEFORMAT=%F %T 

注:ENVIRON 是awk的常量,是数组

格式2:
for(变量;条件;表达式){
语句
}

示例

[root@SZB-L0032013 ~]# awk 'BEGIN{> total=0> for(i=0;i<=100;i++){> total+=i;> }> print total;> }'5050

do循环
do
{语句} while(条件)

示例

[root@SZB-L0032013 ~]# awk 'BEGIN{> total=0;> i=0;> do{total+=i;i++} while(i<=100)> print total;> }'5050

其他语句
break 当break语句用于while或for语句时,导致退出循环
continue当continue语句用于while或for语句是,使程序循环移到下一个迭代
next能够导致读入下一个输入行,并返回到脚本的顶部,这可以避免对当前输入行执行其他的操作过程
exit语句使主输入循环退出并将控制转移到END,如果END存在的话。如果没有定义END规则,或在END中应用exit语句,则终止脚本的执行

数组应用
数组是awk的灵魂,处理文本中最不能少的就是它的数组处理,因为数据索引可以是数字和字符串在awk中数据叫做关联数组,awk中的数组不必提取声明,也不必声明大小,数组元素用0或空字符串来初始化,这根据上下文而定。

数组的定义

Array[1]="sum"Array[2]="kai"Array["first"]="www"Array["last"]="name"

使用中 print Array[1]会打印出sum;使用print Array[2]会打印出kai;使用print[“last”]会得到name

数组相关函数
length返回字符串以及数组长度,split进行分割字符串为数组,也会返回分割得到数组长度

[root@SZB-L0032013 ~]# awk 'BEGIN{info="it is a test";lens=split(info,tA," ");print length(tA),lens;}'4 4

asort对数组进行排序,返回数组长度

[root@SZB-L0032013 ~]# awk 'BEGIN{info="it is a test";lens=split(info,tA," ");print asort(tA);}'4

输出数组内容
for ..in输出,因为数组是关联数组,默认是无序的,所以通过for..in得到的是无序的数组,如果需要
得到有序数组,需要通过下标获得。

[root@SZB-L0032013 ~]# awk 'BEGIN{info="it is a test";lens=split(info,tA," ");for(k in tA){print k,tA[k];}}'4 test1 it2 is3 a

数组的下标是从1开始的

[root@SZB-L0032013 ~]# awk 'BEGIN{info="it is a test";lens=split(info,tA," ");for(k=1;k<=lens;k++){print k,tA[k];}}'1 it2 is3 a4 test

判断键值存在以及删除键值

[root@SZB-L0032013 ~]# awk 'BEGIN{t["a"]="a1";t["b"]="b";if(t["c"]!="c"){print "not in ";};for(k in t){print k,t[k];}}'not in a a1b bc 

以上的代码我们是判断了t[“c”]不存在了,但是我们在遍历数组的时候发现这个键值存在,但是值为空。
这里需要注意,awk数组是关联数组,只要通过数组引用它的key,就会自动创建改序列。
下面这个判断就是正确的。

[root@SZB-L0032013 ~]# awk 'BEGIN{t["a"]="a1";t["b"]="b";if("c" in t){print "not in ";};for(k in t){print k,t[k];}}'a a1b b

删除键值。

[root@SZB-L0032013 ~]# awk 'BEGIN{t["a"]="a1";t["b"]="b";if("b" in t){delete t["b"];};for(k in t){print k,t[k];}}'a a1

二维、多维数组使用
二维多维本质上是多个一维数组组成的。
这里不做过多的介绍,实际使用比较少

[root@SZB-L0032013 ~]# awk 'BEGIN{> for(i=1;i<=9;i++){> for(j=1;j<=9;j++){> tar[i,j]=i*j;print i,"*",j,"=",tar[i,j];> }> }> }'1 * 1 = 11 * 2 = 21 * 3 = 31 * 4 = 4.....9 * 9 = 81

内置函数
awk内置函数,主要分以下3种:算术函数、字符串函数、其它一般函数、时间函数
1、算术函数
atan2(y, x) 返回y/x的反正切
cos(expr) 返回x的余弦;x是弧度
exp(expr) 返回x幂函数
int(expr) 返回x的截断至整数的值
log(expr) 返回x的自然对数
rand() 返回任意数字n,其中0<=n<1
sin(expr) 返回x的正弦;x是弧度
sqrt(expr) 返回x平方根
srand([expr]) 将rand函数的种子值设置为expr参数的值,或如果省略expr参数则使用某天的时间,
返回先前的种子值

OFMT设置输出数据格式是保留3位小数

[root@SZB-L0032013 ~]# awk 'BEGIN{OFMT="%.3f";fs=sin(1);fe=exp(10);f1=log(1);fi=int(3.1415);print fs,fe,f1,fi}'0.841 22026.466 0 3

获取随机数

[root@SZB-L0032013 ~]# awk 'BEGIN{srand();fr=int(100*rand());print fr;}'18[root@SZB-L0032013 ~]# awk 'BEGIN{srand();fr=int(100*rand());print fr;}'55[root@SZB-L0032013 ~]# awk 'BEGIN{srand();fr=int(100*rand());print fr;}'55

2、字符串函数
gensub(r, s, h [, t])返回一个字符串元素数组。
gsub(r, s [, t]) 除了正则表达式所有具体值被替代这点,它和sub函数完全一样的执行
index(s, t) 在由s参数指定的字符串中,返回位置,从1开始编号,如果t参数不在s参数中出现,则返回0
length([s]) 返回s参数指定的字符串的长度,如果未给出s参数,则返回整个记录的长度
split(s, a [, r]) 将s参数指定的参数分割为数组元素,并返回n变量的值,此分割可以通过r参数指定的
扩展正则表达式进行,
sprintf(fmt, expr-list) 根据fmt参数指定的printf子例程格式字符串来格式化expr-list参数指定的表达式
并返回最后生成的字符串
sub(r, s [, t])
substr(s, i [, n]) 返回n指定长度的字符串
tolower(str)转换成小写
toupper(str) 转换成大写

gsub使用

[root@SZB-L0032013 awk]# awk 'BEGIN{info="this is a test2010test!";gsub(/[0-9]+/,"!",info);print info}'this is a test!test!

在info中查找满足正则表达式/[0-9]+/用”“替换,并且替换后的值,赋值给info未给info值,默认是$0

index使用

[root@SZB-L0032013 awk]# awk 'BEGIN{info="this is a test2010test!";print index(info,"test")?"OK":"no found"}'OK

sprintf使用
其中格式化字符串包括两部分内容:一部分是正常字符,这些字符将按原样输出,另一部分是格式化规定字符,以
“%”开始,后跟一个或几个规定字符,用来确定输出内容格式
%d 十进制有符号整数
%u 十进制无符号整数
%f 浮点数
%s 字符串
%c 单个字符
%p 指针的值
%e 指数形式的浮点数
%x %X无符号以十六进制表示的整数
%o 无符号以八进制表示的整数
%g 自动选择合适的表示法

[root@SZB-L0032013 awk]# awk 'BEGIN{n1=124.113;n2=-1.224;n3=1.2345; printf("%.2f,%.2u,%.2g,%X,%on",n1,n2,n3,n1,n1);}'124.11,18446744073709551615,1.2,7C,174n

时间函数
mktime(YYYY MM dd HH MM ss[DST]) 生产时间格式
strftime([forma [,timestamp]]) 格式化时间输出
systime() 得到时间戳 返回从1970年1月1日开始到当前时间的整秒数

[root@SZB-L0032013 awk]# awk 'BEGIN{tstamp=mktime("2001 01 01 12 12 12");print strftime("%c",tstamp)}'Mon 01 Jan 2001 12:12:12 PM CST[root@SZB-L0032013 awk]# awk 'BEGIN{tstamp=mktime("2001 01 01 12 12 12");tstamp2=mktime("2001 02 01 0 0 0");print tstamp2-tstamp1}'980956800[root@SZB-L0032013 awk]# awk 'BEGIN{tstamp=mktime("2001 01 01 12 12 12");tstamp2=systime();print tstamp2-tstamp}'511671684
0 0
原创粉丝点击