AWK只打印某個域後的所有域

前言:
有時我們需要將某個域之後的所有域打印出來,而且每個記錄(行)的域的個數也不一定,所以用“$4,$5,…..$n,….$(NF-1),$NF”窮舉是不現時的,我經過測試,總結了一下實現的方法,供大家參考。
 
一.利用輸出函數printf
// 測試文件內容
[root@cacti tmp]# cat file.txt
x1 x2 x3
x1 x2 x3 x4 x5
x1 x2 x3 x4 x5 x6
x1 x2 x3 x4 x5 x6 x7 x8
x1 x2 x3 x4 x5 x6 x7
 
[root@cacti tmp]# awk '{for(i=4;i<=NF;i++) printf"%s ",$i} {print ""}' file.txt
 
x4 x5
x4 x5 x6
x4 x5 x6 x7 x8
x4 x5 x6 x7
[root@cacti tmp]# awk '{for (i=4;i<=NF;i++) {printf $i" "}printf "\n"}' file.txt
 
x4 x5
x4 x5 x6
x4 x5 x6 x7 x8
x4 x5 x6 x7
 
問題:
1) 在NF不夠4個的記錄(行),將會打印出一個空行;
2) 在輸出的結果中,每行結尾多了一個空格;
 
下面兩種命令,分別對上面兩個命令加了NF>4的判斷,結果是一致的,解決了上面的第一個問題:“在NF不夠4個的記錄(行),將會打印出一個空行;”。
[root@cacti tmp]# awk '{for(i=4;i<=NF;i++) printf"%s ",$i};NF>4 {print ""}' file.txt
x4 x5
x4 x5 x6
x4 x5 x6 x7 x8
x4 x5 x6 x7
[root@cacti tmp]# awk 'NF>4 {for (i=4;i<=NF;i++) {printf $i" "}printf "\n"}' file.txt
x4 x5
x4 x5 x6
x4 x5 x6 x7 x8
x4 x5 x6 x7
 
二.利用字符串函數index和substr
// 測試文件內容
[root@cacti tmp]# cat file.txt
x1 x2 x3
x1 x2 x3 x4 x5
x1 x2 x3 x4 x5 x6
x1 x2 x3 x4 x5 x6 x7 x8
x1 x2 x3 x4 x5 x6 x7
[root@cacti tmp]# cat file.txt |awk '{a=index($0,$4);print substr($0,a)}'
x1 x2 x3
x4 x5
x4 x5 x6
x4 x5 x6 x7 x8
x4 x5 x6 x7
 
可以發現,執行上面這個命令時,在NF不夠4個的記錄(行),將會打印出整行記錄;爲解決這個問題,可以像上文所採用的方法,加上“NF>4”,如下:
[root@cacti tmp]# cat file.txt |awk 'NF>4 {a=index($0,$4);print substr($0,a)}'
x4 x5
x4 x5 x6
x4 x5 x6 x7 x8
x4 x5 x6 x7
 
這種方法似乎很完美,但是分析實現原理,可以發現,本方法是通過分析出$4這個字段的字串 在$0(整個記錄)中第一次出現的位置,記數爲a,之後再截取a之後的字串,並打印。那麼,如果$4的字串在之前就出次過,則a的數值就是前面的出現的位 置了,結果就會是錯誤的,爲解決這個問題,可以將$4替換一下,再定位,測試如下:
// 測試文件內容
[root@cacti tmp]# cat filexx.txt
x1 x2 x3
x1 x4 x3 x4 x5
x1 x4 x4 x4 x5 x6
x4 x2 x3 x4 x5 x6 x7 x8
x1 x2 x3 x4 x4 x6 x7

(本文件,可以發現$4的字串:x4,在2,3,4,5行,在$4之前的域都有出現過與之相同的字串:x4)

//下面是用上面的方法,結果顯然有誤的,是將以x4開始的域之後的所有域全打印出來了。
[root@cacti tmp]# cat filexx.txt |awk 'NF>4 {a=index($0,$4);print substr($0,a)}'
x4 x3 x4 x5
x4 x4 x4 x5 x6
x4 x2 x3 x4 x5 x6 x7 x8
x4 x4 x6 x7
 
//對$4重新賦值,在$4前加個“z”,以區分之前域於之相同的字串
[root@cacti tmp]# cat filexx.txt |awk 'NF>4 {$4="z"$4;a=index($0,$4);print substr($0,a)}'
zx4 x5
zx4 x5 x6
zx4 x5 x6 x7 x8
zx4 x4 x6 x7
 
//將上個命令中加的字串“z”過濾掉,得到想要的結果
[root@cacti tmp]# cat filexx.txt |awk 'NF>4 {$4="n"$4;a=index($0,$4);print substr($0,a+1)}'
x4 x5
x4 x5 x6
x4 x5 x6 x7 x8
x4 x4 x6 x7
 
//指定分隔符爲一個空格,指定(多個)分隔符時,要寫在方括號中,此方法對某個字段(如yang  zhi  gang爲表示名字的字段)中有多個空格很有用。
[root@cacti tmp]# cat filexx.txt |awk 'BIGIN{FS="[ ]"} NF>4 {$4="n"$4;a=index($0,$4);print substr($0,a+1)}'
x4 x5
x4 x5 x6
x4 x5 x6 x7 x8
x4 x4 x6 x7
 
三.利用域值替換
    就是將某個(些)域替換成空值,如去除第一個域爲:awk '{ $1=""; print $0 }' file.in
// 測試文件內容
[root@cacti tmp]# cat file.txt
x1 x2 x3
x1 x2 x3 x4 x5
x1 x2 x3 x4 x5 x6
x1 x2 x3 x4 x5 x6 x7 x8
x1 x2 x3 x4 x5 x6 x7
 
//前3個域用字母a替換
[root@cacti tmp]# awk '{ for(i=1;i<=3;i++){$i="a"}; print $0 }' file.txt
a a a
a a a x4 x5
a a a x4 x5 x6
a a a x4 x5 x6 x7 x8
a a a x4 x5 x6 x7
 
//前3個域用空格替換
[root@cacti tmp]# awk '{ for(i=1;i<=3;i++){$i=""}; print $0 }' file.txt
 
   x4 x5
   x4 x5 x6
   x4 x5 x6 x7 x8
   x4 x5 x6 x7

問題:
1) 在NF不夠4個的記錄(行),將會打印出一個空行;
2) 在輸出的結果中,去除的域會用空格來代替
 
// 去除上面命令輸出的空行,但輸出結果前端會有空格
[root@cacti tmp]# awk 'NF>4 { for(i=1;i<=3;i++){$i=""}; print $0 }' file.txt
   x4 x5
   x4 x5 x6
   x4 x5 x6 x7 x8
   x4 x5 x6 x7
 
總結:
   本文介紹了三種方法來解決AWK“只打印第N個域之後的所有域”的問題。
   第一和第三種方法會出現輸出結果後端或前端加空格的情況,但這可能不會影響你後緒的操作,可以結合管道再處理。
   根據你的需要選擇合適的方法吧。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章