Linux命令之awk:高级输入输出(四)

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为内置变量(当前行号)

  1. 找出匹配行的行号b=NR
  2. 找出输出行的行号a=b+1
  3. 指定输出行号打印
[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

 

转载于:https://my.oschina.net/u/3409834/blog/1548764

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值