1、awk输出匹配行的上下行
- 输出匹配行的上一行语句
awk '/匹配/{print a}{a=$0}'
【原理分析】:
这个awk脚本里有两个大括号,第一个表示匹配到了关键字后才会执行print s;而第二个没有限定,即每一行都会执行s=$0。举个例子,文件abc总共三行,如下:
a
b
c
执行命令awk’/c/{print s}{s=$0}’ abc
输出结果为c 的前一行 b,分析如下:
第一行为a,无法匹配关键字c,所以不执行print s,只执行后面大括号里的内容即将第一行“a” 赋值给变量s;
第二行为c,还是无法匹配到关键字c,不执行print s,只执行s=$0,将第二行“b”赋值给变量s;
第三行为c,可以匹配关键字c,执行命令print s,此时变量s的值为刚刚赋值的“b”,所以输出“b”;之后还会将第三行的全部内容“c”赋值给变量s。
这样就实现了打印关键字的前一行的内容。
[root@sxooky ~]# cat test.txt
300 swk chuyao xianjie $7000
400 zbj wanshua tianting $9500
500 nmw chiyao yaojie $6000
200 awk working beijng $6000
600 cat working beijing $9500
100 mk working beijing $9500
[root@sxooky ~]# awk '/zbj/{print a}{a=$0}' test.txt
300 swk chuyao xianjie $7000
-
输出匹配行的下一行语句
awk '/匹配/{a=NR+1}{if(NR==a)print $0}'
【原理分析】:
与上原理差不多,这个awk脚本里有两个大括号,第一个表示匹配到了关键字后才会执行变量a赋值;而第二个没有限定,即只要条件满足,则都会执行print $0。
注:NR为内置变量(当前行号)
- 找出匹配行的行号b=NR
- 找出输出行的行号a=b+1
- 指定输出行号打印
[root@sxooky ~]# cat test.txt
300 swk chuyao xianjie $7000
400 zbj wanshua tianting $9500
500 nmw chiyao yaojie $6000
200 awk working beijng $6000
600 cat working beijing $9500
100 mk working beijing $9500
[root@sxooky ~]# awk '/zbj/{a=NR+1;next}{if(NR==a)print $0}' test.txt
500 nmw chiyao yaojie $6000
2、awk输出跳过匹配行:
- next:跳过匹配行,读取下一条纪录
[root@sxooky ~]# cat -n test.txt
1 web:www.baidu.com
2 ip=192.168.1.2
3 gateway=192.168.1.1
4 web:www.163.com
5 ip=192.100.100.2
6 gateway=192.100.100.1
7 web:www.qq.com
8 ip=172.10.2.2
9 gateway=172.10.2.1
10 web:www.126.com
11 ip=10.20.1.2
12 gateway=10.20.1.1
[root@sxooky ~]# cat -n test.txt |awk 'NR%2==1{next}{print $0}'
2 ip=192.168.1.2
4 web:www.163.com
6 gateway=192.100.100.1
8 ip=172.10.2.2
10 web:www.126.com
12 gateway=10.20.1.1
- next的应用:匹配行与下一条纪录合并
[root@sxooky ~]# cat test.txt |awk '/web/{t=$0;next}{printf "%20s %20s\n",t,$0}'
web:www.baidu.com ip=192.168.1.2
web:www.baidu.com gateway=192.168.1.1
web:www.163.com ip=192.100.100.2
web:www.163.com gateway=192.100.100.1
web:www.qq.com ip=172.10.2.2
web:www.qq.com gateway=172.10.2.1
web:www.126.com ip=10.20.1.2
web:www.126.com gateway=10.20.1.1
3、找出工资与工作地点一样的员工
根据下面内容完成:第1列是员工编号,第2列是员工姓名,第3列是出勤状态,第4列是工作地点,第5列是工资
300 swk chuyao xianjie $7000
400 zbj wanshua tianting $9500
500 nmw chiyao yaojie $6000
200 awk working beijng $6000
600 cat working beijing $9500
100 mk working beijing $9500
操作方法:
[root@sxooky ~]# cat test.txt
300 swk chuyao xianjie $7000
400 zbj wanshua tianting $9500
500 nmw chiyao yaojie $6000
200 awk working beijng $6000
600 cat working beijing $9500
100 mk working beijing $9500
[root@sxooky ~]# awk 'BEGIN{print "编号\t姓名\t出勤\t\t地点\t\t工资"}{x=$4$5;m[x]=$0 "\n" m[x];n[x]+=1}END{for(i in m){if(n[i]>1)print m[i]}}' test.txt
编号 姓名 出勤 地点 工资
100 mk working beijing $9500
600 cat working beijing $9500
[root@sxooky ~]# awk 'BEGIN{print "编号\t姓名\t出勤\t\t地点\t\t工资"}{x=$4$5;m[x]=$0 "\n" m[x];n[x]+=1}END{for(i in m){if(n[i]>1)print m[i]}}' test.txt |grep -v ^$
编号 姓名 出勤 地点 工资
100 mk working beijing $9500
600 cat working beijing $9500
原理解析:
1、《awk BEGIN语句块执行过程》:BEGIN{print “编号\t姓 名\t出勤\t\t地点\t\t工资”}
输出
编号 姓名 出勤 部门 工资
2、《awk PATTERN语句块执行过程》:{x=$4$5;m[x]=$0 “\n” m[x];n[x]+=1}
- times 1 :
=> m[xianjie$7000 ]="300 swk chuyao xianjie $7000
"
=> n[xianjie$7000]=+1 => n[xianjie$7000]=1
- times 2 :
=> m[tianting$9500]="400 zbj wanshua tianting $9500
"
=> n[tianting$9500]=+1 => n[tianting$9500]=1
- times 3 :
=> m[yaojie$6000]="500 nmw chiyao yaojie $6000
"
=> n[yaojie$6000]=+1 => n[yaojie$6000]=1
- time 4 :
=> m[beijng$6000]="200 awk working beijng $6000
"
=> n[beijng$6000]=+1 => n[beijng$6000]=1
- time 5 :
=> m[beijing$9500]="600 cat working beijing $9500
"
=> n[beijing$9500]=+1 => n[beijing$9500]=1
- time 6 :
=> m[beijing$9500]="100 mk working beijing $9500
600 cat working beijing $9500
"
=> n[beijing$9500]=1+1 => n[beijing$9500]=2
3、《awk END语句块执行过程》:END{for(i in m){if(n[i]>1)print m[i]}}
- 数组m的下标有: xianjie$7000、tianting$9500、yaojie$6000、beijng$6000、beijing$9500
for i in m
=> i= xianjie$7000
=> i= tianting$9500
=> i= yaojie$6000
=> i= beijng$6000
=> i= beijing$9500
if n[i] >1
=> n[xianjie$7000]=1 => pass
=> n[tianting$9500]=1 => pass
=> n[yaojie$6000]=1 => pass
=> n[beijng$6000]=1 => pass
=> n[beijing$9500]=2 => print m[beijing$9500]
- 输出
100 mk working beijing $9500
600 cat working beijing $9500
4、管道过滤:|grep -v ^$
过滤最后的空行”\n”
5、最后结果
[root@sxooky ~]# awk 'BEGIN{print "编号\t姓名\t出勤\t\t部门\t\t工资"}{x=$4$5;m[x]=$0 "\n" m[x];n[x]+=1}END{for(i in m){if(n[i]>1)print m[i]}}' test.txt |grep -v ^$
编号 姓名 出勤 部门 工资
100 mk working beijing $9500
600 cat working beijing $9500