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

一、awk输出匹配行的上下行

  • 输出匹配行的上一行语句
awk '/匹配/{print a}{a=$0}'

【原理分析】:web

这个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
  • 输出匹配行的下一行语句bash

awk '/匹配/{a=NR+1}{if(NR==a)print $0}'

【原理分析】:spa

与上原理差很少,这个awk脚本里有两个大括号,第一个表示匹配到了关键字后才会执行变量a赋值;而第二个没有限定,即只要条件知足,则都会执行print $0。code

注:NR为内置变量(当前行号)ip

  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

 

二、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

三、找出工资与工做地点同样的员工

根据下面内容完成:第1列是员工编号,第2列是员工姓名,第3列是出勤状态,第4列是工做地点,第5列是工资class

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

原理解析:

一、《awk BEGIN语句块执行过程》:BEGIN{print “编号\t姓 名\t出勤\t\t地点\t\t工资”}

输出test

编号 姓名 出勤 部门 工资

二、《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

三、《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 mawk

=> 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

四、管道过滤:|grep -v ^$

过滤最后的空行”\n”

五、最后结果

[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
相关文章
相关标签/搜索