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
相關文章
相關標籤/搜索