這兩天做《linux操作系統》課程的作業,碰到了一個題目,感覺很有意思,很考驗對awk掌握的熟練度,故特意拿來分享。
首先說題目是這樣的,有這樣一段文本:
RECORD#這是多余的注釋行one#record_type students#這是多余的注釋行twoF sno 11111110000F name 王鐵蛋F gender 男F age 20F class 網絡工程01F region 湖北省武漢市.RECORD#這是多余的注釋行one#record_type scores#這是多余的注釋行twoF sno 1205110606F mathematics 92F english 88F chinese 86F history 79F politics 83
然后要我們利用sed和awk,改啊改,改成這個樣子:
這個怎么做呢,首先就是要去掉那個多余的注釋行,那個很好去掉,就是利用sed的正則表達式判斷就好了,以#開頭的,且后面跟著的不是r這個字符,那么就把這行刪除,具體命令如下:
這樣就可以去掉多余的注釋行了。
接下來我們就要進入主題了,利用awk來對文本進行處理。
根據結果來看,可以看到這個題目中awk其實一共錄入了兩個record,也就是說我們的記錄分隔符RS不能再用回車了,得用原文本中的那個點,同時,每條記錄中的每個域應該就是record行到“.”行的每一行,所以我們的域分隔符也應該換一下,變成回車。所以awkBEGIN時執行命令應該是這兩條。
接下來就得要分析,如何打印開頭的那個Record (1) “students”了,括號里面的那個數字應該是當前記錄號,而后面的那個students應該是取自record_type那一行,這個具體要怎么做呢,其實很簡單,如下:
用for循環分別取出每個域,然后判斷,如果以#開頭,那么則說明是#record_type 那一行,我們就對這一行利用gsub函數進行處理。
那個gsub函數是干嘛的呢,其實就是一個替換(substitute)函數,它利用第一個參數里的正則表達式來對第三個參數進行查找,將查找到的內容用第二個參數進行替換。具體到本栗子中就是,查找以#開頭空格結束這么一段內容,然后用空字符串進行替換。這樣其實就是做了一個刪除的功能。這樣處理之后,#record_type students就變成了students了,然后我們再來進行輸出就好了,需要注意的是,PRint函數類似于c語言的printf函數,可以直接對字符串進行連接,所以上面那個print第二個參數其實就是輸出了“students”。
輸出了頭之后,我們就該輸出中間的內容了,我們可以很容易地發現一個規律就是所有內容都是以F開頭的,所以這里我們就可以這樣處理。
首先判斷這個域的內容是不是以F開頭的,如果是,則進行處理。
中間那個split函數的功能就是進行分割,對$i字符串的內容以第三個參數空格進行分割,然后將分割的結果存放到第二個參數所代表的數組中,然后再來將內容輸出就好了。
整個for循環結束之后,再來打印一遍這條記錄結束了,這樣就能實現我們的功能了。
最后再把代碼整體貼一遍,希望對各位有所幫助:
1 #!/bin/bash 2 #History: 3 # Michael 4月,27,2015 4 5 sed '/#[^r].*/d' recordmdA.txt | / 6 7 awk ' 8 BEGIN { 9 RS="."10 FS="/n"11 }12 {13 for(i=1;i<=NF;i++)14 {15 if($i ~ /#.*/)16 {17 gsub(/#.* /,"",$i)18 print "Record ("NR")","/""$i"/""19 }20 else if($i ~ /F.*/)21 {22 split($i,A," ")23 print "/t""/""A[2]"/"""=""/""A[3]"/""24 }25 }26 print "End of Record ("NR")"27 }28 '29 30 # gsub函數的功能就是通過第一個參數的正則表達式在第三個參數中查找特定字符串,然后用第二個參數來替換這個字符串,具體到本例中就是將#record_type score字符串中空格前面的內容全部刪掉31 32 # split函數的功能就是分割,通過第三個參數來將第一個參數的內容進行分割,并將分割的結果存放到第二個參數所代表的數組中
新聞熱點
疑難解答