awk與sed:一個關於多行處理的例子

  前幾天在CSDN上看到一個帖子 http://bbs.csdn.net/topics/390848841 ,樓主貼了下面的問題:
   
   
   
   
例:123456789012345678901234567890如何能把上面數據轉換成123456789012345678901234567890
    看了幾位網友的回覆,以爲仍是挺有意思,也收穫了一些知識,由於部分網友只給出瞭解決方法,沒有解釋下,我根據本身的理解,對幾個答案解釋下(不必定準確,錯誤之處請指正)
我認爲錯的答案
1    首先樓主給出了一個他說調試不出來的答案:
   
   
   
   
sed 's/(?!90)\n//g'
?!應該是非pattern結尾的意思,這個答案應該是說把非90結尾的行的換行符換位空。
這個答案應該是不可行的。sed默認單行模式,一次處理一行,運行時發現,就算咱們把換行符去掉了,sed命令結束後,仍是將它當成完整的一行輸出(也就是說,應該是自動又加上換行符了)
2.    有一位網友,以爲其餘答案太複雜,給出了下面的方法
sed ‘N;s/\n//g’

         這個答案使用了sed的多行模式,但應該是沒法實現樓主的目的的。咱們看運行結果「
windeal@ubuntu:~/Windeal/shell$ sed 'N;s/\n//g' a.txt 
1234567890
1234567890123
4567890

能夠看出,sed 的N命令把第二行接到第一行後面,把第四行接到第三行後面,沒有考慮到咱們目標中:只有非90結尾的才把下一行附加上來。因此第四行的123被附加到第三行1234567890而出現了錯誤的結果。

我認爲對的答案
再來看兩個我認爲對的答案:
1.
sed -e '/^/{:loop /90$/!{N;b loop};s/\n//g}' test.txt > t2.txt
改一下好理解一點就是
sed '{:myloop /90$/!{N;b myloop};s/\n//g}' a.txt

/^/的意思我沒弄明白,應該是匹配每一行吧
      在該命令中,myloop是一個自定義的標籤。相似程序語言中goto用的標籤。 N表示多行模式,b表示分支(至關於goto)
這樣就好理解了,sed會讀取一行內容,若是這一行不是以90結尾,/90$/! 就爲真,進入 {N;b myloop}。N就進入了多行模式,把下一行附加上來,而後進入分支b myloop,在判斷是否是以90結尾,這樣反覆讀取,直到讀到以90結尾的行。接下來模式空間的讀取工做已經完成,進入下一個命令,替換, s/\n//g​這個命令把當前模式空間的換行符都轉換爲空,也就是拼接成一行。
    如此,咱們就完成了咱們要的目的。

2. 
awk '{if($0~/90$/){print}else{printf("%s",$0)}}' a.txt 
這個答案讀取了一行的因此字段(實際上就1個字段,) 用$0表示,而後 if($0~/90$/)判斷是否是以90結尾。
若是以90結尾,就輸出當前行數據。
若是不是,就格式化輸入當前航的字符串
注意print和printf的區別
相關文章
相關標籤/搜索