- 論壇徽章:
- 0
|
本帖最后由 smallpboy 于 2012-08-07 13:15 編輯
文章前本來有說明的,連續(xù)發(fā)表了兩次,修改過的那篇居然沒發(fā)表。這算是我學(xué)sed的筆記吧,但我故意把語句口語化,也是出于方便大家理解的考慮。本文針對(duì)的讀者是學(xué)習(xí)sed的新手,以后我會(huì)補(bǔ)充它或是貼出其他的帖子(例如awk的)。謝謝大家的支持哈。 對(duì)了,文末的問題還請(qǐng)大牛們幫忙解答啊,我加粗顯示了。
•先講n/N的區(qū)別
ywlscpl大牛這么比喻:
如果sed的模式空間對(duì)應(yīng)awk的$0
N相當(dāng)于awk的{v=$0;next;$0=v"\n"$0}
n相當(dāng)于awk的next
用shell來比喻的話
N是: echo 下一行內(nèi)容>>模式空間
n是: echo 下一行內(nèi)容>模式空間
[smallpboy @local tmp]$ seq 4 | sed ‘n;d’
1
3
pattern space先讀入1,然后執(zhí)行到n,把下一行2讀入pattern space中并覆蓋原本的1。然后pattern space中的內(nèi)容(2)被刪除(d操作),所以打印出1\n3。
[smallpboy @local tmp]$ seq 5 | sed ‘n;d’ 你知道它輸出什么嗎?
1
3
5
你猜對(duì)了嗎?
[smallpboy @local tmp]$ seq 4 | sed ‘N;d’
[smallpboy @local tmp]$
什么都沒輸出?對(duì),你沒看錯(cuò)。pattern space先讀入1,然后執(zhí)行到N,把下一行添加到當(dāng)前的pattern space中,pattern space內(nèi)容為(1\n2,對(duì)否?),然后執(zhí)行d操作被刪除。接下去讀入3(系統(tǒng)讀入總是覆蓋原有內(nèi)容),執(zhí)行N,pattern space 內(nèi)容變?yōu)椋?\n4),然后再被刪除。
[smallpboy @local tmp]$ seq 7 | sed ‘N;d’ #你知道它輸出什么嗎?
7
你猜對(duì)了嗎? 簡(jiǎn)單吧?
-n 參數(shù)指不自動(dòng)打印pattern space內(nèi)容,有的人對(duì)它理解不夠?qū)е聹y(cè)試n/N區(qū)別時(shí)被搞的越來越糊涂了。
[smallpboy @local tmp]$ seq 4 | sed –n ‘n’
[smallpboy @local tmp]$ seq 4 | sed –n ‘N’
上述兩個(gè)不輸出任何信息,不用說了吧! :)
[smallpboy @local tmp]$ seq 4 | sed –n ‘n;p’
2
4
這個(gè)能理解么? 參數(shù)p指打印pattern space的內(nèi)容。
[smallpboy @local tmp]$ seq 4 | sed –n ‘N;p’
1
2
3
4
這個(gè)呢?也懂!對(duì)吧。
[smallpboy @local tmp]$ seq 5 | sed –n ‘N;p’
1
2
3
4
這個(gè)呢?也懂吧?再看看這個(gè)
[smallpboy @local tmp]$ seq 5 | sed –n ‘n;p’
自己實(shí)驗(yàn)去。:)自己動(dòng)手才記得牢。
•接下說x
sed有hold space和pattern space,x的意思就是將hold space和pattern space的內(nèi)容交換。咱實(shí)驗(yàn)下,看懂上面n/N區(qū)別的你,看懂下面的實(shí)驗(yàn)就很輕松了。
[smallpboy @local tmp]$ seq 4 | sed –n ‘x;p’
1
2
3
第一行空白?沒錯(cuò),因?yàn)閜attern space讀入1時(shí),hold space還是空的,兩者一交換,pattern space不就成空了嗎?而hold space持有1,對(duì)否?然后,hold space 和 pattern space再交換內(nèi)容,此時(shí)pattern space得到1,hold space得到2,打印pattern space不就打印出1了。
序列最后是4,但只能打印出3,也能理解了吧。因?yàn)?在hold space里了。
在sedline中有一題:在每個(gè)含有字符串regex的行上插入一行空白行。
[smallpboy @local tmp]$ seq 4 | sed ‘/3/{x;p;x;}’
1
2
3
4
看懂了沒?在找到regex的那一行時(shí),pattern space的內(nèi)容不就是這匹配的整行數(shù)據(jù)么,跟hold space交換后,pattern space不就為空了,然后執(zhí)行p操作輸出空行,然后再跟hold space交換內(nèi)容,這時(shí)pattern space不就又拿到其原本的數(shù)據(jù)了嗎?你有可能會(huì)問,括號(hào)里為什么要有p操作啊,命令啥時(shí)自動(dòng)輸出pattern space內(nèi)容?額,這個(gè)你可是試試把p去掉后結(jié)果是怎么樣的啊,看下結(jié)果你就懂啦;蛘呤悄憧慈缦虏僮
[smallpboy @local tmp]$ seq 4 | sed ‘/3/{x;p;x;d}’
1
2
4
我們的操作都是括號(hào)里面,所以輸出刪除等操作由你自己決定啦。這樣解釋x操作能懂了吧?
•接下去講h/H,分別為復(fù)制(覆蓋)/添加pattern space到hold space。
這個(gè)沒什么例子能單獨(dú)舉的呢。不行?必須要例子。。額。好吧,看下面。
[smallpboy @local tmp]$ seq 4 | sed ‘x’ #還記得結(jié)果嗎?跟sed –n ‘x;p’一樣的哦。
1
2
3
[smallpboy @local tmp]$ seq 4 | sed ‘h;x’
1
2
3
4
很容易懂吧?h操作把pattern space內(nèi)容復(fù)制到hold space去了。x操作交換它倆的內(nèi)容,兩者一模一樣,交換個(gè)啥啊。:)
[smallpboy @local tmp]$ seq 4 | sed ‘x;h’
額,我浪費(fèi)版面?額,我哭。是輸出四個(gè)空行啦。x操作把空的hold space和pattern space交換,然后空的pattern space又把它自己復(fù)制給hold space,這樣hold space和pattern space永遠(yuǎn)都成空了。╮(╯▽╰)╭,解釋清楚了沒?
•接下去講g/G,分別為復(fù)制(覆蓋)/添加hold space到pattern space。
假如你想要把能匹配regex的這一行變成空行,可以考慮用g哦。假如你想要把能匹配regex的這一行下一行再添加一空行,可以考慮用G哦。
[smallpboy @local tmp]$ seq 4 | sed ‘/3/g’
1
2
4
原理?額,不用多說了吧。想不通?你再想想。額,很簡(jiǎn)單。我還是smallpboy啊,大鳥飛過就好了嘛。
sed其他:
1、 wc –l功能:
sed –n ‘$=’ filename
“=”操作指打印行號(hào),可以執(zhí)行sed –n ‘=’ filename仔細(xì)體會(huì)下它和-n之間的關(guān)系!$”指最后一行。
2、 tac 功能
sed ‘1!G;h;$!d’ filename
G和h操作還記得么?忘了就去前面看看吧。這里難懂的還有“1!”和“$!”,其實(shí)它倆很簡(jiǎn)單,在其他語言中就是“!1”和“!$”這樣,即非第一行,非最后一行的意思。這塊能懂嗎?類似的,刪除空行使用 sed ‘/^$/d’,那刪除非空行呢?刪除非空行?對(duì),使用sed ‘/^$/!d’就好了嘛。好了,如果了解了“1!”和“$!”的意思了,現(xiàn)在可以開始分解上述命令了。
[smallpboy @local tmp]$ seq 3 | sed ‘1!;G’
1
2
3
“1”下面沒有空行是否在你預(yù)料之內(nèi)呢?G操作在第二行(也就是第二次操作)之后才起作用。
[smallpboy @local tmp]$ seq 3 | sed ‘1!;G;h’
這個(gè)就復(fù)雜了,h操作將pattern space內(nèi)容復(fù)制到hold space,第一次讀入1時(shí),G操作被禁止,pattern space內(nèi)容為1吧。然后h操作將這個(gè)1復(fù)制過去了。第二次讀入2時(shí),G操作將hold space內(nèi)容添加到pattern space(結(jié)果為2\n1,能跟上我的思路不?),然后h操作將hold space的內(nèi)容從第一次結(jié)束時(shí)的1,更新為2\n1,也就是第二次結(jié)束的結(jié)果。這樣,當(dāng)讀入3時(shí)(也即是第三次),G操作將pattern space變成了3\n2\n1。是否?:)所以上述命令輸出如下:
1
2\n1
3\n2\n1
能看懂么?當(dāng)然,終端上可不會(huì)顯示“\n”字符的哈。最后,指保留最后一行,大功告成:
[smallpboy @local tmp]$ seq 3 | sed ‘1!;G;h;$!d’
3
2
1
這樣,全懂了吧? ╮(╯▽╰)╭,說的好糾結(jié),好婆媽啊。^)^
3、 rev功能
sed ‘/\n/!G;s/\(.\)\(.*\n\)/&\2\1;//D;s/.//;’
實(shí)話說,這個(gè)命令確實(shí),我也半懂不懂的,確實(shí)很復(fù)雜啊。勉強(qiáng)說下:
“/\n/!G;”這個(gè)能理解不?在stdin中沒有找到\n,就主動(dòng)添上\n。
“s/\(.\)\(.*\n\)/&\2\1;”中\(zhòng)(.\)先匹配一個(gè)字符,再匹配剩下所有字符!&”指整個(gè)pattern space,\2和\1想必你也知道是什么東東。
“//D”指刪除pattern space第一行,space非空就循環(huán)執(zhí)行。“s/.//”就不解釋了。假設(shè)我們有文件:
[smallpboy @local tmp]$ cat file
123
file文件中“123\n”執(zhí)行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的結(jié)果為123\n23\n1。
[smallpboy @local tmp]$ cat file | sed ‘/\n/!G;s/\(.\)\(.*\n\)/&\2\1;//D’
這個(gè)復(fù)雜了,咋們嚴(yán)肅點(diǎn)一步一步來說。上面說到第一次執(zhí)行s….后,結(jié)果(誰的結(jié)果?這個(gè)還要提示么?pattern space啊。)為123\n23\n1,然后要執(zhí)行//D命令了,結(jié)果為23\n1。
然后到開頭繼續(xù)執(zhí)行/\n/!G;,pattern space(舊的)不變,然后執(zhí)行s….后,新的pattern space為23\n3\n21(\1為2,\2為3\n,&為23\n),然后執(zhí)行//D,結(jié)果為3\n21。
再執(zhí)行/\n/!G;,pattern space(下一操作s….會(huì)產(chǎn)生新的pattern space把這個(gè)給覆蓋)不變,執(zhí)行s….,結(jié)果變?yōu)?\n\n321(\1為3,\2為\n,&為3\n),再執(zhí)行//D操作,結(jié)果為\n321,此結(jié)果還不為空。
繼續(xù)執(zhí)行/\n/!G;,pattern space不變,然后執(zhí)行s….,發(fā)現(xiàn)匹配不了,此時(shí)pattern space沒有被重新賦值。執(zhí)行//D操作后,結(jié)果為321。然后,然后,就發(fā)現(xiàn)錯(cuò)了。。。。。
[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
最后一步根本沒有執(zhí)行//D操作,或是執(zhí)行//D沒有刪除“\n321”前面這個(gè)“\n”?D的解釋是delete up to the first embedded newline of the current pattern space。額,這個(gè)D是只能刪除 新的pattern space 的第一行嗎? 小弟我也沒有明白,還請(qǐng)大牛們解釋下了,文章也只能寫到這里了。
|
|