sed-n/N/g/G/h/H/x…

  文章前本來有說明的,連續發表了兩次,修改過的那篇居然沒發表。這算是我學sed的筆記吧,但我故意把語句口語化,也是出於方便大家理解的考慮。本文針對的讀者是學習sed的新手,以後我會補充它或是貼出其他的帖子(例如awk的)。謝謝大家的支持哈。 對了,文末的問題還請大牛們幫忙解答啊,我加粗顯示了。

     •先講n/N的區別
ywlscpl大牛這麼比喻:
如果sed的模式空間對應awk的$0
N相當於awk的{v=$0;next;$0=v"\n"$0}
n相當於awk的next

用shell來比喻的話
N是:  echo 下一行內容>>模式空間
n是:  echo 下一行內容>模式空間

[smallpboy @local tmp]$ seq 4 | sed ‘n;d’
1
3
pattern space先讀入1,然後執行到n,把下一行2讀入pattern space中並覆蓋原本的1。然後pattern space中的內容(2)被刪除(d操作),所以打印出1\n3。
[smallpboy @local tmp]$ seq 5 | sed ‘n;d’          你知道它輸出什麼嗎? 
1
3
5
你猜對了嗎?
[smallpboy @local tmp]$ seq 4 | sed ‘N;d’
[smallpboy @local tmp]$
什麼都沒輸出?對,你沒看錯。pattern space先讀入1,然後執行到N,把下一行添加到當前的pattern space中,pattern space內容爲(1\n2,對否?),然後執行d操作被刪除。接下去讀入3(系統讀入總是覆蓋原有內容),執行N,pattern space 內容變爲(3\n4),然後再被刪除。
[smallpboy @local tmp]$ seq 7 | sed ‘N;d’       #你知道它輸出什麼嗎?
7
你猜對了嗎? 簡單吧? 

        -n 參數指不自動打印pattern space內容,有的人對它理解不夠導致測試n/N區別時被搞的越來越糊塗了。
[smallpboy @local tmp]$ seq 4 | sed –n ‘n’
[smallpboy @local tmp]$ seq 4 | sed –n ‘N’ 
上述兩個不輸出任何信息,不用說了吧! :)
[smallpboy @local tmp]$ seq 4 | sed –n ‘n;p’      
2
4
這個能理解麼? 參數p指打印pattern space的內容。
[smallpboy @local tmp]$ seq 4 | sed –n ‘N;p’
1
2
3
4
這個呢?也懂!對吧。
[smallpboy @local tmp]$ seq 5 | sed –n ‘N;p’
1
2
3
4
這個呢?也懂吧?再看看這個
[smallpboy @local tmp]$ seq 5 | sed –n ‘n;p’
自己實驗去。:)自己動手才記得牢。

•接下說x
sed有hold space和pattern space,x的意思就是將hold space和pattern space的內容交換。咱實驗下,看懂上面n/N區別的你,看懂下面的實驗就很輕鬆了。
[smallpboy @local tmp]$ seq 4 | sed –n ‘x;p’

1
2
3
第一行空白?沒錯,因爲pattern space讀入1時,hold space還是空的,兩者一交換,pattern space不就成空了嗎?而hold space持有1,對否?然後,hold space 和 pattern space再交換內容,此時pattern space得到1,hold space得到2,打印pattern space不就打印出1了。
序列最後是4,但只能打印出3,也能理解了吧。因爲4在hold space裏了。
        在sedline中有一題:在每個含有字符串regex的行上插入一行空白行。
[smallpboy @local tmp]$ seq 4 | sed ‘/3/{x;p;x;}’
1
2

3
4
看懂了沒?在找到regex的那一行時,pattern space的內容不就是這匹配的整行數據麼,跟hold space交換後,pattern space不就爲空了,然後執行p操作輸出空行,然後再跟hold space交換內容,這時pattern space不就又拿到其原本的數據了嗎?你有可能會問,括號裏爲什麼要有p操作啊,命令啥時自動輸出pattern space內容啊?額,這個你可是試試把p去掉後結果是怎麼樣的啊,看下結果你就懂啦。或者是你看如下操作
[smallpboy @local tmp]$ seq 4 | sed ‘/3/{x;p;x;d}’
1
2

4
我們的操作都是括號裏面,所以輸出刪除等操作由你自己決定啦。這樣解釋x操作能懂了吧?

•接下去講h/H,分別爲複製(覆蓋)/添加pattern space到hold space。
這個沒什麼例子能單獨舉的呢。不行?必須要例子。。額。好吧,看下面。
[smallpboy @local tmp]$ seq 4 | sed ‘x’       #還記得結果嗎?跟sed –n ‘x;p’一樣的哦。

1
2
3
[smallpboy @local tmp]$ seq 4 | sed ‘h;x’
1
2
3
4
很容易懂吧?h操作把pattern space內容複製到hold space去了。x操作交換它倆的內容,兩者一模一樣,交換個啥啊。:)
[smallpboy @local tmp]$ seq 4 | sed ‘x;h’




額,我浪費版面?額,我哭。是輸出四個空行啦。x操作把空的hold space和pattern space交換,然後空的pattern space又把它自己複製給hold space,這樣hold space和pattern space永遠都成空了。╮(╯▽╰)╭,解釋清楚了沒?

•接下去講g/G,分別爲複製(覆蓋)/添加hold space到pattern space。
假如你想要把能匹配regex的這一行變成空行,可以考慮用g哦。假如你想要把能匹配regex的這一行下一行再添加一空行,可以考慮用G哦。
[smallpboy @local tmp]$ seq 4 | sed ‘/3/g’
1
2

4
原理?額,不用多說了吧。想不通?你再想想。額,很簡單。我還是smallpboy啊,大鳥飛過就好了嘛。

sed其他:
1、        wc –l功能:
sed –n ‘$=’ filename     
“=”操作指打印行號,可以執行sed –n ‘=’ filename仔細體會下它和-n之間的關係。“$”指最後一行。
2、        tac 功能
sed ‘1!G;h;$!d’ filename
G和h操作還記得麼?忘了就去前面看看吧。這裏難懂的還有“1!”和“$!”,其實它倆很簡單,在其他語言中就是“!1”和“!$”這樣,即非第一行,非最後一行的意思。這塊能懂嗎?類似的,刪除空行使用 sed ‘/^$/d’,那刪除非空行呢?刪除非空行?對,使用sed ‘/^$/!d’就好了嘛。好了,如果瞭解了“1!”和“$!”的意思了,現在可以開始分解上述命令了。
[smallpboy @local tmp]$ seq 3 | sed ‘1!;G’
1
2

3

“1”下面沒有空行是否在你預料之內呢?G操作在第二行(也就是第二次操作)之後才起作用。
[smallpboy @local tmp]$ seq 3 | sed ‘1!;G;h’
這個就複雜了,h操作將pattern space內容複製到hold space,第一次讀入1時,G操作被禁止,pattern space內容爲1吧。然後h操作將這個1複製過去了。第二次讀入2時,G操作將hold space內容添加到pattern space(結果爲2\n1,能跟上我的思路不?),然後h操作將hold space的內容從第一次結束時的1,更新爲2\n1,也就是第二次結束的結果。這樣,當讀入3時(也即是第三次),G操作將pattern space變成了3\n2\n1。是否?:)所以上述命令輸出如下:
1
2\n1
3\n2\n1
能看懂麼?當然,終端上可不會顯示“\n”字符的哈。最後,指保留最後一行,大功告成:
[smallpboy @local tmp]$ seq 3 | sed ‘1!;G;h;$!d’
3
2
1
這樣,全懂了吧? ╮(╯▽╰)╭,說的好糾結,好婆媽啊。^)^

3、        rev功能
sed ‘/\n/!G;s/\(.\)\(.*\n\)/&\2\1;//D;s/.//;’
實話說,這個命令確實,我也半懂不懂的,確實很複雜啊。勉強說下:
“/\n/!G;”這個能理解不?在stdin中沒有找到\n,就主動添上\n。
“s/\(.\)\(.*\n\)/&\2\1;”中\(.\)先匹配一個字符,再匹配剩下所有字符。“&”指整個pattern space,\2和\1想必你也知道是什麼東東。
“//D”指刪除pattern space第一行,space非空就循環執行。“s/.//”就不解釋了。假設我們有文件:
[smallpboy @local tmp]$ cat file
123
file文件中“123\n”執行s/\(.\)\(.*\n\)/&\2\1;
[smallpboy @local tmp]$ cat file | sed ‘/\n/!G;s/\(.\)\(.*\n\)/&\2\1;’
123
23
1
上面可能讀懂?“123\n”分別被匹配爲\1(1)和\2(23\n),所以&\2\1的結果爲123\n23\n1。
[smallpboy @local tmp]$ cat file | sed ‘/\n/!G;s/\(.\)\(.*\n\)/&\2\1;//D’
這個複雜了,咋們嚴肅點一步一步來說。上面說到第一次執行s….後,結果(誰的結果?這個還要提示麼?pattern space啊。)爲123\n23\n1,然後要執行//D命令了,結果爲23\n1。
然後到開頭繼續執行/\n/!G;,pattern space(舊的)不變,然後執行s….後,新的pattern space爲23\n3\n21(\1爲2,\2爲3\n,&爲23\n),然後執行//D,結果爲3\n21。
再執行/\n/!G;,pattern space(下一操作s….會產生新的pattern space把這個給覆蓋)不變,執行s….,結果變爲3\n\n321(\1爲3,\2爲\n,&爲3\n),再執行//D操作,結果爲\n321,此結果還不爲空。
繼續執行/\n/!G;,pattern space不變,然後執行s….,發現匹配不了,此時pattern space沒有被重新賦值。執行//D操作後,結果爲321。然後,然後,就發現錯了。。。。。
[smallpboy @local tmp]$ cat file | sed ‘/\n/!G;s/\(.\)\(.*\n\)/&\2\1;P;//D’  
123
23
3

321
#P print up to the first embedded newline of the current pattern space。
[smallpboy @local tmp]$ cat file | sed ‘/\n/!G;s/\(.\)\(.*\n\)/&\2\1;//D’

321
最後一步根本沒有執行//D操作,或是執行//D沒有刪除“\n321”前面這個“\n”?D的解釋是delete up to the first embedded newline of the current pattern space。額,這個D是隻能刪除 新的pattern space 的第一行嗎? 小弟我也沒有明白,還請大牛們解釋下了,文章也只能寫到這裏了

 

轉自http://bbs.chinaunix.net/thread-3763371-1-9.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章