- 論壇徽章:
- 0
|
本帖最后由 where27 于 2010-03-15 14:12 編輯
AWK one-line寫的非常之好,前些日子我嘗試翻譯了一下,對(duì)我自己的能力也有了一點(diǎn)提升,最近又看了一下Famous Sed One-Liners Explained,覺得sed的難度比awk有過之而無不及啊,一度非常崩潰,幸好堅(jiān)持了下去,加上一直在cu的shell版塊發(fā)帖子提問,在黑哥等人的幫助下,也算馬馬虎虎看完了,為了造福一下部分像我這種sed菜鳥,我將看過的這些內(nèi)容翻譯一下,請(qǐng)大家批評(píng)指正。謝謝!
先進(jìn)入第一部分:空行,編號(hào),以及文本轉(zhuǎn)換
開始翻譯之前我想講一下sed程序的執(zhí)行流程,還是舉一個(gè)例子說明吧- #more file
- 123
- 456
- #sed ‘/5/p’ file
- 123
- 456
- 456
- # sed –n ‘/5/p’ file
- 456
復(fù)制代碼 和awk類似,sed 語句的基本結(jié)構(gòu)也是 sed ‘模式{動(dòng)作1;動(dòng)作2}’file 。同樣也是匹配模式才執(zhí)行動(dòng)作。不過sed中有兩個(gè)空間大家一定要記住,一個(gè)叫pattern space(模式空間),一個(gè)叫hold buffer(緩沖區(qū)/緩沖空間),sed中的模式匹配的對(duì)象只是模式空間,而動(dòng)作{p,d,n,g..etc}則的對(duì)象是模式空間和緩沖空間。和awk一樣,sed也是一行一行的讀入文本,不過sed在執(zhí)行命令前,會(huì)將文本的行讀到模式空間中,然后執(zhí)行模式{動(dòng)作}語句,而在執(zhí)行命令完后,默認(rèn)sed還是把模式空間的內(nèi)容打印出來(通過-n 參數(shù)可以把最后默認(rèn)打印模式空間的動(dòng)作取消)。在上面的例子中,首先sed把123讀入到模式空間中,由于模式/5/不匹配123,因此后面動(dòng)作p(打印當(dāng)前模式空間的內(nèi)容)也就不執(zhí)行了,正如之前說的,sed在讀入下一行456之前會(huì)執(zhí)行默認(rèn)的打印動(dòng)作p,把123打印出來。繼續(xù)讀下一行456,由于模式/5/匹配456,執(zhí)行動(dòng)作p把456打印出來,而后默認(rèn)又打印了一次456。這就是sed命令的一個(gè)基本流程。當(dāng)然大多數(shù)情況下我們只是想要把匹配模式的內(nèi)容打印出來,這里加一個(gè)-n參數(shù)就可以了。
Tips:在sed讀入下一行前會(huì)把模式空間清空,所以當(dāng)讀第二行456的時(shí)候,模式空間內(nèi)的123已經(jīng)沒了。
一、 空行
1. 輸出兩倍行距文件這個(gè)例子使用了G命令,這個(gè)命令把緩沖空間的內(nèi)容附加到模式空間,由于沒有命令對(duì)緩沖空間做操作(只有h,H,x三個(gè)命令可以對(duì)緩沖空間做操作),所有緩沖空間的內(nèi)容一直為空,因此只是簡(jiǎn)單的附加了一個(gè)換行符\n在模式空間后面,執(zhí)行完G以后,sed默認(rèn)執(zhí)行打印的動(dòng)作將123\n打印出來,因此輸出的內(nèi)容里面就多了一個(gè)空行。
2. 輸出兩倍行距文件(文件有空行,非空行之間間隔不超過一個(gè)空行)- #more file
- 123
- 456
- #sed ‘/^$/d;G’ file
- 123
- 456
復(fù)制代碼 Sed中的只有匹配模式的行才執(zhí)行動(dòng)作。這個(gè)例子中有兩個(gè)模式{動(dòng)作}語句,第一個(gè)語句只有當(dāng)行匹配/^$/的時(shí)候才進(jìn)行操作,^$代表空行大家應(yīng)該都知道吧,sed對(duì)空行執(zhí)行動(dòng)作d,這個(gè)命令的意思是刪除當(dāng)前模式空間的內(nèi)容,開始新的循環(huán)。怎么理解呢?其實(shí)就是把模式空間的空行清空以后,不再執(zhí)行后面的命令,也不執(zhí)行默認(rèn)的打印動(dòng)作,而是返回到開頭,讀取下一行的內(nèi)容到模式空間,繼續(xù)執(zhí)行命令。所以說是開始新的循環(huán)。簡(jiǎn)單來說就是讀到空行就把它刪除,然后重新讀取下一行。當(dāng)sed讀到非空行的時(shí)候,不匹配模式,因此不執(zhí)行d,G沒有模式限制,因此去執(zhí)行G,跟例1一樣,加一個(gè)空行在后面,打印出來,在繼續(xù)讀下一行,因此得到以上輸出。
3. 輸出3被行距這個(gè)沒什么好講的,兩次G,也就是附加兩個(gè)回車在文本的后面,打印出來。
4. 只打印奇數(shù)行文本- #more file
- 123
- 456
- 789
- abc
- #sed ‘n;d’ file
- 123
- 789
復(fù)制代碼 這里出現(xiàn)了一個(gè)新的命令n,命令n的作用是:打印當(dāng)前模式空間的內(nèi)容(如果前面加了參數(shù)-n則不打。,然后清空模式空間,把下一行讀入到模式空間中。然后執(zhí)行d,即刪除模式空間內(nèi)容,在回到開頭。所以大家可以發(fā)現(xiàn),打印出來的都是奇數(shù)行,而偶數(shù)行都被d刪除了。
5. 在匹配正則表達(dá)式/5/的行的前面插入一個(gè)空行- #sed ‘/5/{x;p;x}’ file
- 123
- 456
- 789
復(fù)制代碼 出現(xiàn)了一個(gè)新的命令x,之前講到x命令可以操作緩沖空間,具體就是把模式空間的內(nèi)容和緩沖空間的內(nèi)容交換,模式/5/只匹配第二行的456,因此對(duì)第一行和第三行,就是默認(rèn)打印出來而已,當(dāng)讀入456的時(shí)候,x將模式空間內(nèi)容的456與緩沖空間的內(nèi)容交換(默認(rèn)是空),接著把打印模式空間的空行,再執(zhí)行x,這個(gè)時(shí)候緩沖空間里有456,又把456還給模式空間,最后執(zhí)行默認(rèn)的打印動(dòng)作,把456打印出來。
Tips:{x;p;x}是一個(gè)命令群組,匹配模式才按順序執(zhí)行他們。
6. 在匹配正則表達(dá)式/5/的行的后面插入一個(gè)空行- #sed ‘/5/G’ file
- 123
- 456
- 789
復(fù)制代碼 這個(gè)例子和第一個(gè)例子類似,只不過G只對(duì)456這行操作,因此只在第二行后面附加一個(gè)空行。
7. 在匹配正則表達(dá)式/5/所在行的前后兩行都加上一個(gè)空行這個(gè)例子其實(shí)就是5,6的合體,讀入456后,先執(zhí)行x;p打印出空行,然后執(zhí)行x;G,打印出456和空行,也就是在456的前后各有一個(gè)空行。
二、 編號(hào)
8. 給文本的每行編號(hào),并把行號(hào)放在行的左邊- #sed = file|sed ‘N;s/\n/\t/’
- 1 123
- 2 456
- 3 789
復(fù)制代碼 有一點(diǎn)點(diǎn)復(fù)雜了,這個(gè)語句其實(shí)可以分成兩個(gè),第一個(gè)使用了新的命令=,作用是直接把當(dāng)前行的行號(hào)打印出來,因?yàn)闆]有辦法直接把行號(hào)附加到模式空間去,所有才利用管道符號(hào)執(zhí)行第二個(gè)sed命令來實(shí)現(xiàn)這個(gè)功能。第二個(gè)sed又有了一個(gè)新的命令N,這個(gè)命令的作用就是附加一個(gè)\n和下一行的內(nèi)容到當(dāng)前的模式空間去,同樣s///命令也是sed中非;镜囊粋(gè)命令,s/\n/\t/的作用是如果模式空間內(nèi)有\(zhòng)n,就把\n換成\t也就是制表符,然后再把模式空間的內(nèi)容打印出來
我們來看看這兩個(gè)命令分別執(zhí)行的過程執(zhí)行第一個(gè)sed = file后- #sed = file
- 1
- 123
- 2
- 456
- 3
- 789
復(fù)制代碼 第二個(gè)語句是針對(duì)第一個(gè)語句的輸出來做操作的,來看sed ‘N;s/\n/\t/’ ,首先模式空間內(nèi)容是1,N將換行\(zhòng)n和123附加到了1的后面,因此模式空間就變成了1\n456,s/\n/\t/則把換行符\n換成了制表符\t,由此模式空間就變成了1\t123,然后打印出來,其他依次類推,所以得到了以下內(nèi)容9. 給文本每行編號(hào),并把行號(hào)右對(duì)齊。- #sed = file | sed 'N; s/^/ /; s/ *\(.\{6,\}\)\n/\1 /'
復(fù)制代碼 這個(gè)例子也包含了兩部分,第一部分跟例8一樣給每行編號(hào),第二部分使用命令N把沒兩行的內(nèi)容連在一起,然后使用兩個(gè)替換命令把行號(hào)右對(duì)齊,第一個(gè)替換命令在行的開頭加上了5個(gè)空格,第二個(gè)替換命令在換行符\n前提取至少6個(gè)字符,然后把獲取的內(nèi)容和換行符用之前標(biāo)記的內(nèi)容\1在這里(\1指的是之前第一個(gè)被\(\)括起來的內(nèi)容,同理第二個(gè)被\(\)括起來的內(nèi)容可以用\2來代替,依次類推。。)和兩個(gè)空格代替,空格用來把行號(hào)和文本分隔開。
第二部分讀起來可能有點(diǎn)難懂,我們看一個(gè)例子,為了表達(dá)的更清晰,我們用@來代替\n,用-來代替空格。- # echo "-----12@contents" | sed 's/-*\(.\{6,\}\)@/\1--/'
- ----12--contents
復(fù)制代碼 這個(gè)正則表達(dá)式 ‘-*\(.\{6,\}\)@’ (或者只是 ‘-*(.{6,})@’) 匹配任意個(gè)-,然后是6個(gè)其他的字符,接著是一個(gè)符號(hào)@,sed
他們提取出來,并保存起來以供后面的\1調(diào)用。首先sed匹配一個(gè)-然后是緊接著的六個(gè)字符----12和@,接著s命令把之前匹配的內(nèi)容替換成\1(也就是之前保存起來的六個(gè)字符----12)和--.最終的結(jié)果就是把”-----12@”變成了”----12”.
10. 只給非空行編號(hào)- #more file
- 123
- 456
- 789
- # sed '/./=' file | sed '/./N; s/\n/ /'
- 1 123
- 2 456
- 4 789
復(fù)制代碼 這個(gè)例子也是分成了兩個(gè)部分,第一部分的輸出通過管道符|傳遞給第二部分當(dāng)做第二部分的輸入,第一部分使用正則表達(dá)式/./過濾出至少一個(gè)字符的行,當(dāng)sed把空行放入模式空間后,由于不匹配模式,因此也不對(duì)其執(zhí)行=這個(gè)編號(hào)的命令。第二部分和第八例題一樣也是把兩行合并成一行后,替換\n為空格,然后打印出來。
11. 計(jì)算文件的行數(shù)(類似wc –l的作用)這個(gè)sed例子使用了參數(shù)-n去修飾執(zhí)行的動(dòng)作,-n使得在模式空間被處理完后,并不執(zhí)行默認(rèn)的p把模式空間內(nèi)容打印出來,想在在-n參數(shù)下輸出內(nèi)容,只能使用一些命令(=,a,I,i,p,P,c,r,w..etc),這個(gè)例子中,模式部分是$,匹配文件的最后一行,動(dòng)作也=,也就是打印行號(hào),因此輸出是最后一行的行號(hào),也就是行的數(shù)量。
三、 文本替換
Sed one-liner中在這里介紹了很多關(guān)于windows格式文本轉(zhuǎn)為unix格式文本,大家要知道在windows下面是用兩個(gè)字符分行即回車+換行,而unix下只有一個(gè)換行,cu里相關(guān)的內(nèi)容有很多,我就不加介紹了。
12. 刪除每行的空白符(包括空格和制表符)- #more file
- 123
- 456
- 789
- #sed ‘s/^[ \t]*//’ file
- 123
- 456
- 789
復(fù)制代碼 這個(gè)很簡(jiǎn)單,s將每行中匹配行首(^匹配行首)任意個(gè)空白的行,并把這些空白刪除,僅此而已。
13. 刪除每行結(jié)尾的空白行這個(gè)也沒什么好講的,匹配行尾有任意個(gè)空白的行,并把空白刪除
14. 同時(shí)刪除行首和行尾的空白- # sed 's/^[ \t]*//;s/[ \t]*$//' file
復(fù)制代碼 只是兩個(gè)例子的合體而已。
15. 每行的開頭添加兩個(gè)空白- #more file
- 123
- 456
- 789
- #sed ‘s/^/ /’ file
- 123
- 456
- 789
復(fù)制代碼 在行首的位置加上兩個(gè)空白,僅此而已。
16. 右對(duì)齊文本(文本寬度為21個(gè)字符)- # sed -e :a -e 's/^.\{1,20\}$/ &/;ta' file
- 123
- 456
- 789
復(fù)制代碼 這個(gè)例子中sed出現(xiàn)了一個(gè)新的參數(shù)-e,-e的作用是允許sed把一段語句分成若干部分,當(dāng)sed執(zhí)行命令前,會(huì)先將這些部分組合起來,再執(zhí)行命令。我們通常把一段sed分成若干部分是因?yàn)檫@些部分分別完成不同的功能,分開后比較容易讀懂。第一個(gè)部分的命令之前大家也沒有見過,是一個(gè)冒號(hào)和a,作用是創(chuàng)建一個(gè)名字叫a的標(biāo)簽。第二部分sed使用了一個(gè)新的命令t,t的作用是如果前一個(gè)s/../../命令執(zhí)行成功,那么sed將跳轉(zhuǎn)到指定的標(biāo)簽,這里ta也就是跳轉(zhuǎn)到之前的標(biāo)簽a這里,這個(gè):a .s/../../.ta,構(gòu)成了一個(gè)循環(huán),也就是說只要模式空間的內(nèi)容能夠執(zhí)行s/../../替換命令,sed就通過t把替換后的文本再重新執(zhí)行替換,周而復(fù)始,直到模式空間的內(nèi)容不滿足s/../../的匹配要求,才終止循環(huán),打印出模式空間的內(nèi)容。
下面來看一下替換命令s/^.\{1,19\}$/ &/,其中^.\{1,19\}$匹配包含1個(gè)或19個(gè)字符的行,后面的&則是代表前一個(gè)模式中的內(nèi)容,也就是.\{1,19\},簡(jiǎn)單說就是,當(dāng)模式空間的內(nèi)容是1個(gè)或19個(gè)字符的時(shí)候,就在模式空間的內(nèi)容前面加上一個(gè)空格,如果前面的循環(huán)大家看的懂的話,就可以可以看懂這個(gè)例子了:就是把每行的內(nèi)容前面加上一個(gè)個(gè)的空白,直到這行的長(zhǎng)度超過了19個(gè)字符,當(dāng)文本寬度是20個(gè)字符的時(shí)候,sed就不再加空格了,直接打印出文本。
類似一個(gè)while循環(huán)- # while (str.length() <= 21) {
- str = " " + str
- }
復(fù)制代碼 17. 文本居中(寬度為21字符)- # sed -e :a -e 's/^.\{1,20\}$/ & /;ta' file
- 123
- 456
- 789
復(fù)制代碼 這個(gè)例子很前一個(gè)幾乎一樣,不同的是在添加空格的時(shí)候,左右都添加了,當(dāng)文本的長(zhǎng)度達(dá)到21個(gè)字符的時(shí)候,前后的空白字符的個(gè)數(shù)也一樣,也就達(dá)到了文本居中的目的了。
18. 替換文本每行中第一次出現(xiàn)的1為a- #more file
- 123123123
- 456
- 789
- #sed ‘s/1/a/’ file
- a23123123
- 456
- 789
復(fù)制代碼 一個(gè)簡(jiǎn)單的替換語句,把文本中每行的第一個(gè)1替換成a
19. 替換每行出現(xiàn)的第二個(gè)1為a- #sed ‘s/1/a/2’ file
- 123a23123
- 456
- 789
復(fù)制代碼 其實(shí)這才是替換語句的完成格式,把每行中出現(xiàn)的第二個(gè)1替換成a,沒有這個(gè)2的話,sed默認(rèn)為1,也就是上一題的匹配第一個(gè)出現(xiàn)的1
20. 把所有行中的1替換成a- #sed ‘s/1/a/g’ file
- a23a23a23
- 456
- 789
復(fù)制代碼 這里使用了另一個(gè)位置參數(shù)g,代表所有,也就是把所有的1都替換成a
21. 如果一個(gè)行出現(xiàn)了2個(gè)1,則替換第一個(gè)1為a- #more file
- 123123
- 4561
- 789
- #sed ‘s/\(.*\)1\(.*1\)/\1a\2/’ file
- a23123
- 4561
- 789
復(fù)制代碼 作用大家都很清楚了,只是在s替換語句中出現(xiàn)了2個(gè)組\(..\),第一個(gè)組里包含了在第一個(gè)1前面的所有字符,而第二個(gè)組里包含了從第一個(gè)1后到第二個(gè)1截止(包含第二個(gè)1)的所有字符。因此這個(gè)替換語句的模式中包含了2個(gè)1,但只是替換第一個(gè)1為a,這也是為什么在第二行中也有1,為什么不會(huì)被替換成a的原因,因?yàn)榈诙兄挥幸粋(gè)1,不匹配s替換語句中的模式。
22. 替換每行中最后一次出現(xiàn)的1為a- #sed ‘s/\(.*\)1/a/’ file
- 123a23
- 4561
- 789
復(fù)制代碼 同樣使用了字符組,匹配的是1前面的所有字符,之所以會(huì)把最后出現(xiàn)的1替換成a,是因?yàn)?*是最大匹配,比如說在第一行123123中,.*1能匹配1,和1231,但是默認(rèn)匹配最大也就是1231,因此替換的是最后一個(gè)1.
23. 在包含6的行中把所有1都替換成a- #sed ‘/6/s/1/a/g’ file
- 123123
- 456a
- 789
復(fù)制代碼 改例子使用了一個(gè)正則表達(dá)式/6/去限制替換命令的使用,也就是說只有匹配6的行才能夠執(zhí)行替換。
24. 在不含6的行中把所有1都替換成6- #sed ‘/6/!s/1/a/g’ file
- a23a23
- 4561
- 789
復(fù)制代碼 Sed可以使用反向匹配,也就是不匹配的行執(zhí)行動(dòng)作,在這里,不匹配6的第一行中的1都被換成了a,第二行中有6,所以不把1換成a
25. 替換1或者6或者9為a- #sed ‘s/1/a/g;s/6/a/g;s/9/a/g’ file
- a23a23
- 45aa
- 78a
復(fù)制代碼 這里使用了3個(gè)s替換語句去匹配和替換。如果你用的是gnu版本的sed,就可以用下面的語句- #sed ‘s/1|6|9/a/g’ file
- a23a23
- 45aa
- 78a
復(fù)制代碼 Sed提供了更高級(jí)的正則表達(dá)式功能包含了間隔符|,這里的1\|6\|9就是表示匹配1或者6或者9
26. 倒序文本(類似tac的作用)- #more file
- 123
- 456
- 789
- #sed ‘1!G;h;$!d’ file
- 789
- 456
- 123
復(fù)制代碼 終于到了一個(gè)稍微有點(diǎn)難度的例子了,首先我們來解釋一個(gè)這個(gè)命令,G:前面講過,就是把緩沖區(qū)的內(nèi)容附加在模式空間的后面(以\n分隔)。h:將模式空間的內(nèi)容把緩沖區(qū)的內(nèi)容覆蓋,這時(shí)候緩沖區(qū)的內(nèi)容和模式空間一樣了d:當(dāng)然就是把模式空間的內(nèi)容刪除,并返回到開頭。我們來逐行看一下
第一行:1!G的意思是出了第一行其他行都執(zhí)行G,因此跳過,直接到h,把模式空間的內(nèi)容拷到緩沖區(qū)中,緩沖區(qū)中的內(nèi)容是123接著執(zhí)行d,返回到了開頭,繼續(xù)讀下一行456
第二行:第二行可以執(zhí)行G命令,即把緩沖區(qū)123的內(nèi)容附加到模式空間中456的后面,并以\n分隔,因此模式空間的內(nèi)容為456\n123,h后,緩沖區(qū)的內(nèi)容也變成了456\n123,同樣d后,什么都不輸出直接到下一行
第三行:執(zhí)行G,附加緩沖區(qū)的456\n123到789的后面,及模式空間變成789\n456\n123,同時(shí)緩沖區(qū)通過h也變成了789\n456\n123,最后的$!d的意思是最后一行不執(zhí)行d的動(dòng)作,也就是命令到此結(jié)束了,sed默認(rèn)把模式空間的789\n456\n123打印出來,也就是大家看到的結(jié)果了,下面的流程可以幫助大家理解。
讀入文本 命令 模式空間 緩沖空間 打印結(jié)果
123 1!G 123 空 空
h 123 123 空
$!d 空 123 空
456 1!G 456\n123 123 空
h 456\n123 456\n123 空
$!d 空 456\n123 空
789 1!G 789\n456\n123 456\n123 空
h 789\n456\n123 789\n456\n123 空
$!d 789\n456\n123 789\n456\n123 789\n456\n123
最后打印出來的789\n456\n123也就是我們要的結(jié)果了。
另一種寫法- # sed -n '1!G;h;$p' file
- 789
- 456
- 123
復(fù)制代碼 -n防止sed默認(rèn)的p動(dòng)作,而只在最后一行的時(shí)候把模式空間的東西打印出來
指的一提的是,這個(gè)例子會(huì)在執(zhí)行的過程中會(huì)使用大量的內(nèi)存,因?yàn)樗诖蛴〕龅剐虻奈谋局鞍颜麄(gè)文件的內(nèi)容都保存在緩沖區(qū)里面,所以如果文件的行數(shù)過多的話,還是不要使用這個(gè)語句吧。
27. 翻轉(zhuǎn)每行的內(nèi)容(類似rev的作用)- # sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//' file
- 321
- 654
- 987
復(fù)制代碼 這個(gè)命令的結(jié)構(gòu)非常復(fù)雜,可以把它分成4個(gè)部分- #sed '
- /\n/!G
- s/\(.\)\(.*\n\)/&\2\1/
- //D
- s/.//
- '
復(fù)制代碼 我們一個(gè)個(gè)來分析,以第一行123為例
/\n/!G:如果模式空間的內(nèi)容不包括\n,把緩沖區(qū)的內(nèi)容附加到模式空間后,以\n分隔,緩沖區(qū)的內(nèi)容為空除非有命令對(duì)其進(jìn)行操作,這樣執(zhí)行過后模式空間的內(nèi)容變成123\n
s/\(.\)\(.*\n\)/&\2\1/:s替換的模式部分包含了2個(gè)字符組,字符組1只包含了1個(gè)任意字符,第二個(gè)字符組包括了剩余的字符和\n,&代表的是前面整個(gè)匹配項(xiàng),也就是123\n,例如,在執(zhí)行完這個(gè)語句后,模式空間的內(nèi)容123\n就變成了123\n23\n1
//D:這個(gè)語句是整個(gè)sed例子的關(guān)鍵,一個(gè)空的匹配//,表示匹配上一個(gè)出現(xiàn)的正則表達(dá)式,這里也就是/\(.\)\(.*\n\)/D了,D的作用是刪除模式空間中從開始到第一個(gè)\n截止的字符,并從第一個(gè)命令開始重新執(zhí)行sed(不讀到下一行)。實(shí)際上是創(chuàng)建了一個(gè)循環(huán),也就是只要模式空間的\n前面有一個(gè)字符,就把\n和前面的字符刪除,剩余的內(nèi)容傳遞到第一個(gè)命令繼續(xù)執(zhí)行,只有\(zhòng)n前面沒有字符了,循環(huán)才結(jié)束。
S/.//:意思很簡(jiǎn)單,刪除模式空間的第一個(gè)字符,但是這個(gè)命令執(zhí)行的條件就是D不執(zhí)行,也就是說模式空間中\(zhòng)n前面沒有字符,后面后經(jīng)過翻轉(zhuǎn)后的內(nèi)容,其實(shí)就是把\n給刪除了,接著默認(rèn)sed輸出翻轉(zhuǎn)后的內(nèi)容,還是來看一下流程吧
讀入文本 命令 模式空間 緩沖空間 打印結(jié)果
123 /\n/!G 123\n 空 空
s/\(.\)\(.*\n\)/&\2\1/ 123\n23\n1 空
//D 23\n1 空 空
D執(zhí)行成功,循環(huán)到開頭執(zhí)行/\n/!G
/\n/!G 23\n1 空 空
s/\(.\)\(.*\n\)/&\2\1/ 23\n3\n21 空 空
//D 3\n21 空 空
D執(zhí)行成功,循環(huán)到開頭執(zhí)行/\n/!G
/\n/!G 3\n21 空 空
s/\(.\)\(.*\n\)/&\2\1/ 3\n\n321 空 空
//D \n321 空 空
D執(zhí)行成功,循環(huán)到開頭執(zhí)行/\n/!G
/\n/!G \n321 空 空
s/\(.\)\(.*\n\)/&\2\1 \n321 空 空
//D \n321 空 空
模式不匹配,開始執(zhí)行s/.// 321 空 321
把321打印出來了,累死我了。。
28. 把文本兩行合成一行- #more file
- 123
- 456
- 789
- abc
- #sed ‘$!N;s/\n/ /’ file
- 123 456
- 789 abc
復(fù)制代碼 這個(gè)例子使用N將兩個(gè)連續(xù)的行組合成一個(gè)新行,他們之間通過\n連接,因此第二個(gè)替換語句將\n換成空格,就得到了輸出,由于最后一行沒有下一行可以連接,所以N的前面是$!
29. 如果行的結(jié)尾是\,就把下一行附加到這一行末尾。- #more file
- 123\
- 456\
- 789
- abc
- #sed –e :a–e ‘/\\$/N;s/\\\n/ /;ta’
- 123 456 789
- abc
復(fù)制代碼 第一個(gè)命令:a,創(chuàng)建了一個(gè)標(biāo)簽a,而第二個(gè)命令判斷模式空間的內(nèi)容是否是以\結(jié)尾,如果是,則執(zhí)行N把\n和下一行附加到這行的結(jié)尾,然后執(zhí)行s替換,把中間的\\n換成空格,如果成功,則ta把模式空間的內(nèi)容循環(huán)到標(biāo)簽的位置繼續(xù)處理,也就是判斷附加的那行是否還是以\結(jié)尾,如果是,繼續(xù)附加,循環(huán)下去。如果不是,打印出模式空間的內(nèi)容。
Tips:如果沒有這個(gè)循環(huán)的話,就不能檢查每一行的結(jié)尾是否是\.
30. 如果行的開頭是=,就把這行附加到上一行的結(jié)尾。- #more file
- 123
- =456
- =789
- abc
復(fù)制代碼- #sed –e :a –e ‘$!N;s/\n=/ /;ta’ –e ‘P;D’ file
- 123 456 789
- abc
復(fù)制代碼 這個(gè)例子的開頭也創(chuàng)建了一個(gè)標(biāo)簽a,然后檢測(cè)文本是不是最后一行,如果不是就把下一行附加到這一行的結(jié)尾,以\n分隔,如果正好下一行的開頭是=,則使用替換命令s把換行符\n和=替換成一個(gè)空格,如果替換成功,則ta把命令循環(huán)至標(biāo)簽a的位置,然后繼續(xù)附加下一行,檢查下一行是否是以=開頭,是的話就替換,依次循環(huán),知道下一行的開頭不是=,則循環(huán)結(jié)束,開始執(zhí)行后面的命令P;D,P的意思是打印模式空間中從一個(gè)字符到第一個(gè)\n為止的所有字符,D的意思是刪除第一個(gè)字符到\n截止的所以字符,其實(shí)也就是刪除剛才打印過的字符,然后回到開頭。繼續(xù)讀下一行
上面的例子中,第一行和第二行第三行之所以連在了一起,就是因?yàn)榈诙泻偷谌惺且?開頭。
31. 將數(shù)字組以千分位的方式分成串- #echo "1234567"|sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta'
- 1,234,567
復(fù)制代碼 這個(gè)例子首先創(chuàng)建一個(gè)標(biāo)簽a,然后模式替換部分分成了兩個(gè)組,第一個(gè)組在最后3個(gè)數(shù)字之前是任意個(gè)字符加上一個(gè)數(shù)字,第二個(gè)組是最后的三個(gè)數(shù)字,替換的結(jié)果是在兩組之間加上一個(gè)逗號(hào),然后又是循環(huán)開始,知道所有的數(shù)字都3個(gè)一組的被逗號(hào)分隔。
看看上面的例子,第二個(gè)組里包含的是數(shù)字1234,第二個(gè)組里包含的是567,加上逗號(hào)后變成1234,567
由于替換成功,循環(huán)開始,這次第一個(gè)組里包含的是1,第二個(gè)組里包含的是234,替換過后,1234,567就變成了1,234,567,接著循環(huán),由于1,234,567中沒有連續(xù)的四個(gè)數(shù)字,所有替換不成立,sed默認(rèn)打印出模式空間的內(nèi)容,也就是1,234,567。
如果sed的版本是gnu的,則可以簡(jiǎn)寫成- #echo "1234567"|sed ':a;s/\B[0-9]\{3\}\>/,&/;ta'
- 1,234,567
復(fù)制代碼 不同的地方在于包含3個(gè)數(shù)字的字符組是如何匹配的。重點(diǎn)在于這個(gè)\B,它是一個(gè)位置字符,不占空間,匹配任何地方但是不包含字符分界線如空格,分號(hào),逗號(hào),冒號(hào)等而最后的\>,匹配的是單詞的分界如逗號(hào)。
32. 每2行加一個(gè)空行- #more file
- 123
- 456
- 789
- abc
- #sed ‘n;G’ file
- 123
- 456
- 789
- abc
復(fù)制代碼 前講過,n命令的作用是打印當(dāng)前行,然后清空,把下一行讀入,G把一個(gè)空行加到了下一行的結(jié)尾,這樣也就是打印了兩行之后在打印一個(gè)空行了。
GNU版本的sed還有另一種寫法- #sed ‘0~2G’ file
- 123
- 456
- 789
- abc
復(fù)制代碼 這個(gè)其實(shí)也好理解,就是從還沒有讀入行開始,也就是0行,每過兩行就執(zhí)行一個(gè)G,也就是添加一個(gè)空行,大家記住這個(gè)格式就可以了。
好了第一部分完成了,加油! |
|