亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

Chinaunix

標(biāo)題: Famous Sed One-Liners Explained中文版 [打印本頁(yè)]

作者: where27    時(shí)間: 2010-03-15 14:09
標(biāo)題: Famous Sed One-Liners Explained中文版
本帖最后由 where27 于 2010-03-15 14:12 編輯

AWK one-line寫(xiě)的非常之好,前些日子我嘗試翻譯了一下,對(duì)我自己的能力也有了一點(diǎn)提升,最近又看了一下Famous Sed One-Liners Explained,覺(jué)得sed的難度比awk有過(guò)之而無(wú)不及啊,一度非常崩潰,幸好堅(jiān)持了下去,加上一直在cu的shell版塊發(fā)帖子提問(wèn),在黑哥等人的幫助下,也算馬馬虎虎看完了,為了造福一下部分像我這種sed菜鳥(niǎo),我將看過(guò)的這些內(nèi)容翻譯一下,請(qǐng)大家批評(píng)指正。謝謝!
先進(jìn)入第一部分:空行,編號(hào),以及文本轉(zhuǎn)換

開(kāi)始翻譯之前我想講一下sed程序的執(zhí)行流程,還是舉一個(gè)例子說(shuō)明吧
  1. #more file
  2. 123
  3. 456
  4. #sed ‘/5/p’ file
  5. 123
  6. 456
  7. 456
  8. # sed –n ‘/5/p’ file
  9. 456
復(fù)制代碼
和awk類(lèi)似,sed 語(yǔ)句的基本結(jié)構(gòu)也是 sed ‘模式{動(dòng)作1;動(dòng)作2}’file 。同樣也是匹配模式才執(zhí)行動(dòng)作。不過(guò)sed中有兩個(gè)空間大家一定要記住,一個(gè)叫pattern space(模式空間),一個(gè)叫hold buffer(緩沖區(qū)/緩沖空間),sed中的模式匹配的對(duì)象只是模式空間,而動(dòng)作{p,d,n,g..etc}則的對(duì)象是模式空間和緩沖空間。和awk一樣,sed也是一行一行的讀入文本,不過(guò)sed在執(zhí)行命令前,會(huì)將文本的行讀到模式空間中,然后執(zhí)行模式{動(dòng)作}語(yǔ)句,而在執(zhí)行命令完后,默認(rèn)sed還是把模式空間的內(nèi)容打印出來(lái)(通過(guò)-n 參數(shù)可以把最后默認(rèn)打印模式空間的動(dòng)作取消)。在上面的例子中,首先sed把123讀入到模式空間中,由于模式/5/不匹配123,因此后面動(dòng)作p(打印當(dāng)前模式空間的內(nèi)容)也就不執(zhí)行了,正如之前說(shuō)的,sed在讀入下一行456之前會(huì)執(zhí)行默認(rèn)的打印動(dòng)作p,把123打印出來(lái)。繼續(xù)讀下一行456,由于模式/5/匹配456,執(zhí)行動(dòng)作p把456打印出來(lái),而后默認(rèn)又打印了一次456。這就是sed命令的一個(gè)基本流程。當(dāng)然大多數(shù)情況下我們只是想要把匹配模式的內(nèi)容打印出來(lái),這里加一個(gè)-n參數(shù)就可以了。
Tips:在sed讀入下一行前會(huì)把模式空間清空,所以當(dāng)讀第二行456的時(shí)候,模式空間內(nèi)的123已經(jīng)沒(méi)了。
一、        空行
1.        輸出兩倍行距文件
  1. #sed ‘G’ file
  2. 123

  3. 456
復(fù)制代碼
這個(gè)例子使用了G命令,這個(gè)命令把緩沖空間的內(nèi)容附加到模式空間,由于沒(méi)有命令對(duì)緩沖空間做操作(只有h,H,x三個(gè)命令可以對(duì)緩沖空間做操作),所有緩沖空間的內(nèi)容一直為空,因此只是簡(jiǎn)單的附加了一個(gè)換行符\n在模式空間后面,執(zhí)行完G以后,sed默認(rèn)執(zhí)行打印的動(dòng)作將123\n打印出來(lái),因此輸出的內(nèi)容里面就多了一個(gè)空行。
2.        輸出兩倍行距文件(文件有空行,非空行之間間隔不超過(guò)一個(gè)空行)
  1. #more file
  2. 123

  3. 456
  4. #sed ‘/^$/d;G’ file
  5. 123

  6. 456
復(fù)制代碼
Sed中的只有匹配模式的行才執(zhí)行動(dòng)作。這個(gè)例子中有兩個(gè)模式{動(dòng)作}語(yǔ)句,第一個(gè)語(yǔ)句只有當(dāng)行匹配/^$/的時(shí)候才進(jìn)行操作,^$代表空行大家應(yīng)該都知道吧,sed對(duì)空行執(zhí)行動(dòng)作d,這個(gè)命令的意思是刪除當(dāng)前模式空間的內(nèi)容,開(kāi)始新的循環(huán)。怎么理解呢?其實(shí)就是把模式空間的空行清空以后,不再執(zhí)行后面的命令,也不執(zhí)行默認(rèn)的打印動(dòng)作,而是返回到開(kāi)頭,讀取下一行的內(nèi)容到模式空間,繼續(xù)執(zhí)行命令。所以說(shuō)是開(kāi)始新的循環(huán)。簡(jiǎn)單來(lái)說(shuō)就是讀到空行就把它刪除,然后重新讀取下一行。當(dāng)sed讀到非空行的時(shí)候,不匹配模式,因此不執(zhí)行d,G沒(méi)有模式限制,因此去執(zhí)行G,跟例1一樣,加一個(gè)空行在后面,打印出來(lái),在繼續(xù)讀下一行,因此得到以上輸出。
3.        輸出3被行距
  1. #sed ‘G;G’ file
復(fù)制代碼
這個(gè)沒(méi)什么好講的,兩次G,也就是附加兩個(gè)回車(chē)在文本的后面,打印出來(lái)。
4.        只打印奇數(shù)行文本
  1. #more file
  2. 123
  3. 456
  4. 789
  5. abc
  6. #sed ‘n;d’ file
  7. 123
  8. 789
復(fù)制代碼
這里出現(xiàn)了一個(gè)新的命令n,命令n的作用是:打印當(dāng)前模式空間的內(nèi)容(如果前面加了參數(shù)-n則不打。,然后清空模式空間,把下一行讀入到模式空間中。然后執(zhí)行d,即刪除模式空間內(nèi)容,在回到開(kāi)頭。所以大家可以發(fā)現(xiàn),打印出來(lái)的都是奇數(shù)行,而偶數(shù)行都被d刪除了。
5.        在匹配正則表達(dá)式/5/的行的前面插入一個(gè)空行
  1. #sed ‘/5/{x;p;x}’ file
  2. 123

  3. 456
  4. 789
復(fù)制代碼
出現(xiàn)了一個(gè)新的命令x,之前講到x命令可以操作緩沖空間,具體就是把模式空間的內(nèi)容和緩沖空間的內(nèi)容交換,模式/5/只匹配第二行的456,因此對(duì)第一行和第三行,就是默認(rèn)打印出來(lái)而已,當(dāng)讀入456的時(shí)候,x將模式空間內(nèi)容的456與緩沖空間的內(nèi)容交換(默認(rèn)是空),接著把打印模式空間的空行,再執(zhí)行x,這個(gè)時(shí)候緩沖空間里有456,又把456還給模式空間,最后執(zhí)行默認(rèn)的打印動(dòng)作,把456打印出來(lái)。
Tips:{x;p;x}是一個(gè)命令群組,匹配模式才按順序執(zhí)行他們。
6.        在匹配正則表達(dá)式/5/的行的后面插入一個(gè)空行
  1. #sed ‘/5/G’ file
  2. 123
  3. 456

  4. 789
復(fù)制代碼
這個(gè)例子和第一個(gè)例子類(lèi)似,只不過(guò)G只對(duì)456這行操作,因此只在第二行后面附加一個(gè)空行。
7.        在匹配正則表達(dá)式/5/所在行的前后兩行都加上一個(gè)空行
  1. #sed ‘/5/{x;p;x;G}’ file
復(fù)制代碼
這個(gè)例子其實(shí)就是5,6的合體,讀入456后,先執(zhí)行x;p打印出空行,然后執(zhí)行x;G,打印出456和空行,也就是在456的前后各有一個(gè)空行。
二、        編號(hào)
8.        給文本的每行編號(hào),并把行號(hào)放在行的左邊
  1. #sed = file|sed ‘N;s/\n/\t/’
  2. 1   123
  3. 2   456
  4. 3   789
復(fù)制代碼
有一點(diǎn)點(diǎn)復(fù)雜了,這個(gè)語(yǔ)句其實(shí)可以分成兩個(gè),第一個(gè)使用了新的命令=,作用是直接把當(dāng)前行的行號(hào)打印出來(lái),因?yàn)闆](méi)有辦法直接把行號(hào)附加到模式空間去,所有才利用管道符號(hào)執(zhí)行第二個(gè)sed命令來(lái)實(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)容打印出來(lái)
我們來(lái)看看這兩個(gè)命令分別執(zhí)行的過(guò)程
  1. #more file
  2. 123
  3. 456
  4. 789
復(fù)制代碼
執(zhí)行第一個(gè)sed = file后
  1. #sed = file
  2. 1
  3. 123
  4. 2
  5. 456
  6. 3
  7. 789
復(fù)制代碼
第二個(gè)語(yǔ)句是針對(duì)第一個(gè)語(yǔ)句的輸出來(lái)做操作的,來(lái)看sed ‘N;s/\n/\t/’ ,首先模式空間內(nèi)容是1,N將換行\(zhòng)n和123附加到了1的后面,因此模式空間就變成了1\n456,s/\n/\t/則把換行符\n換成了制表符\t,由此模式空間就變成了1\t123,然后打印出來(lái),其他依次類(lèi)推,所以得到了以下內(nèi)容
  1. 1   123
  2. 2   456
  3. 3   789
復(fù)制代碼
9.        給文本每行編號(hào),并把行號(hào)右對(duì)齊。
  1. #sed = file | sed 'N; s/^/     /; s/ *\(.\{6,\}\)\n/\1  /'
復(fù)制代碼
這個(gè)例子也包含了兩部分,第一部分跟例8一樣給每行編號(hào),第二部分使用命令N把沒(méi)兩行的內(nèi)容連在一起,然后使用兩個(gè)替換命令把行號(hào)右對(duì)齊,第一個(gè)替換命令在行的開(kāi)頭加上了5個(gè)空格,第二個(gè)替換命令在換行符\n前提取至少6個(gè)字符,然后把獲取的內(nèi)容和換行符用之前標(biāo)記的內(nèi)容\1在這里(\1指的是之前第一個(gè)被\(\)括起來(lái)的內(nèi)容,同理第二個(gè)被\(\)括起來(lái)的內(nèi)容可以用\2來(lái)代替,依次類(lèi)推。。)和兩個(gè)空格代替,空格用來(lái)把行號(hào)和文本分隔開(kāi)。
  第二部分讀起來(lái)可能有點(diǎn)難懂,我們看一個(gè)例子,為了表達(dá)的更清晰,我們用@來(lái)代替\n,用-來(lái)代替空格。
  1. # echo "-----12@contents" | sed 's/-*\(.\{6,\}\)@/\1--/'
  2. ----12--contents
復(fù)制代碼
這個(gè)正則表達(dá)式 ‘-*\(.\{6,\}\)@’ (或者只是 ‘-*(.{6,})@’) 匹配任意個(gè)-,然后是6個(gè)其他的字符,接著是一個(gè)符號(hào)@,sed
他們提取出來(lái),并保存起來(lái)以供后面的\1調(diào)用。首先sed匹配一個(gè)-然后是緊接著的六個(gè)字符----12和@,接著s命令把之前匹配的內(nèi)容替換成\1(也就是之前保存起來(lái)的六個(gè)字符----12)和--.最終的結(jié)果就是把”-----12@”變成了”----12”.
10.        只給非空行編號(hào)
  1. #more file
  2. 123
  3. 456

  4. 789
  5. # sed '/./=' file | sed '/./N; s/\n/ /'
  6. 1 123
  7. 2 456

  8. 4 789
復(fù)制代碼
這個(gè)例子也是分成了兩個(gè)部分,第一部分的輸出通過(guò)管道符|傳遞給第二部分當(dāng)做第二部分的輸入,第一部分使用正則表達(dá)式/./過(guò)濾出至少一個(gè)字符的行,當(dāng)sed把空行放入模式空間后,由于不匹配模式,因此也不對(duì)其執(zhí)行=這個(gè)編號(hào)的命令。第二部分和第八例題一樣也是把兩行合并成一行后,替換\n為空格,然后打印出來(lái)。
11.        計(jì)算文件的行數(shù)(類(lèi)似wc –l的作用)
  1. #sed -n '$=' file
  2. 4
復(fù)制代碼
這個(gè)sed例子使用了參數(shù)-n去修飾執(zhí)行的動(dòng)作,-n使得在模式空間被處理完后,并不執(zhí)行默認(rèn)的p把模式空間內(nèi)容打印出來(lá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è)字符分行即回車(chē)+換行,而unix下只有一個(gè)換行,cu里相關(guān)的內(nèi)容有很多,我就不加介紹了。
12.        刪除每行的空白符(包括空格和制表符)
  1. #more file
  2. 123
  3.     456
  4. 789
  5. #sed ‘s/^[ \t]*//’ file
  6. 123
  7. 456

  8. 789
復(fù)制代碼
這個(gè)很簡(jiǎn)單,s將每行中匹配行首(^匹配行首)任意個(gè)空白的行,并把這些空白刪除,僅此而已。
13.        刪除每行結(jié)尾的空白行
  1. #sed ‘s/[ \t]*$/’ file
復(fù)制代碼
這個(gè)也沒(méi)什么好講的,匹配行尾有任意個(gè)空白的行,并把空白刪除
14.        同時(shí)刪除行首和行尾的空白
  1. # sed 's/^[ \t]*//;s/[ \t]*$//' file
復(fù)制代碼
只是兩個(gè)例子的合體而已。

15.        每行的開(kāi)頭添加兩個(gè)空白
  1. #more file
  2. 123
  3. 456
  4. 789
  5. #sed ‘s/^/  /’ file
  6.   123
  7.   456
  8.   789
復(fù)制代碼
在行首的位置加上兩個(gè)空白,僅此而已。
16.        右對(duì)齊文本(文本寬度為21個(gè)字符)
  1. # sed -e :a -e 's/^.\{1,20\}$/ &/;ta' file
  2.                  123
  3.                  456
  4.                  789
復(fù)制代碼
這個(gè)例子中sed出現(xiàn)了一個(gè)新的參數(shù)-e,-e的作用是允許sed把一段語(yǔ)句分成若干部分,當(dāng)sed執(zhí)行命令前,會(huì)先將這些部分組合起來(lái),再執(zhí)行命令。我們通常把一段sed分成若干部分是因?yàn)檫@些部分分別完成不同的功能,分開(kāi)后比較容易讀懂。第一個(gè)部分的命令之前大家也沒(méi)有見(jiàn)過(guò),是一個(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),也就是說(shuō)只要模式空間的內(nèi)容能夠執(zhí)行s/../../替換命令,sed就通過(guò)t把替換后的文本再重新執(zhí)行替換,周而復(fù)始,直到模式空間的內(nèi)容不滿足s/../../的匹配要求,才終止循環(huán),打印出模式空間的內(nèi)容。
   下面來(lái)看一下替換命令s/^.\{1,19\}$/ &/,其中^.\{1,19\}$匹配包含1個(gè)或19個(gè)字符的行,后面的&則是代表前一個(gè)模式中的內(nèi)容,也就是.\{1,19\},簡(jiǎn)單說(shuō)就是,當(dāng)模式空間的內(nèi)容是1個(gè)或19個(gè)字符的時(shí)候,就在模式空間的內(nèi)容前面加上一個(gè)空格,如果前面的循環(huán)大家看的懂的話,就可以可以看懂這個(gè)例子了:就是把每行的內(nèi)容前面加上一個(gè)個(gè)的空白,直到這行的長(zhǎng)度超過(guò)了19個(gè)字符,當(dāng)文本寬度是20個(gè)字符的時(shí)候,sed就不再加空格了,直接打印出文本。
   類(lèi)似一個(gè)while循環(huán)
  1. # while (str.length() <= 21) {
  2. str = " " + str
  3. }
復(fù)制代碼
17.        文本居中(寬度為21字符)
  1. # sed  -e :a -e 's/^.\{1,20\}$/ & /;ta' file
  2.          123         
  3.          456         
  4.          789  
復(fù)制代碼
這個(gè)例子很前一個(gè)幾乎一樣,不同的是在添加空格的時(shí)候,左右都添加了,當(dāng)文本的長(zhǎng)度達(dá)到21個(gè)字符的時(shí)候,前后的空白字符的個(gè)數(shù)也一樣,也就達(dá)到了文本居中的目的了。
18.        替換文本每行中第一次出現(xiàn)的1為a
  1. #more file
  2. 123123123
  3. 456
  4. 789
  5. #sed ‘s/1/a/’ file
  6. a23123123
  7. 456
  8. 789
復(fù)制代碼
一個(gè)簡(jiǎn)單的替換語(yǔ)句,把文本中每行的第一個(gè)1替換成a
19.        替換每行出現(xiàn)的第二個(gè)1為a
  1. #sed ‘s/1/a/2’ file
  2. 123a23123
  3. 456
  4. 789
復(fù)制代碼
其實(shí)這才是替換語(yǔ)句的完成格式,把每行中出現(xiàn)的第二個(gè)1替換成a,沒(méi)有這個(gè)2的話,sed默認(rèn)為1,也就是上一題的匹配第一個(gè)出現(xiàn)的1
20.        把所有行中的1替換成a
  1. #sed ‘s/1/a/g’ file
  2. a23a23a23
  3. 456
  4. 789
復(fù)制代碼
這里使用了另一個(gè)位置參數(shù)g,代表所有,也就是把所有的1都替換成a
21.        如果一個(gè)行出現(xiàn)了2個(gè)1,則替換第一個(gè)1為a
  1. #more file
  2. 123123
  3. 4561
  4. 789
  5. #sed ‘s/\(.*\)1\(.*1\)/\1a\2/’ file
  6. a23123
  7. 4561
  8. 789
復(fù)制代碼
作用大家都很清楚了,只是在s替換語(yǔ)句中出現(xiàn)了2個(gè)組\(..\),第一個(gè)組里包含了在第一個(gè)1前面的所有字符,而第二個(gè)組里包含了從第一個(gè)1后到第二個(gè)1截止(包含第二個(gè)1)的所有字符。因此這個(gè)替換語(yǔ)句的模式中包含了2個(gè)1,但只是替換第一個(gè)1為a,這也是為什么在第二行中也有1,為什么不會(huì)被替換成a的原因,因?yàn)榈诙兄挥幸粋(gè)1,不匹配s替換語(yǔ)句中的模式。
22.        替換每行中最后一次出現(xiàn)的1為a
  1. #sed ‘s/\(.*\)1/a/’ file
  2. 123a23
  3. 4561
  4. 789
復(fù)制代碼
同樣使用了字符組,匹配的是1前面的所有字符,之所以會(huì)把最后出現(xiàn)的1替換成a,是因?yàn)?*是最大匹配,比如說(shuō)在第一行123123中,.*1能匹配1,和1231,但是默認(rèn)匹配最大也就是1231,因此替換的是最后一個(gè)1.
23.        在包含6的行中把所有1都替換成a
  1. #sed ‘/6/s/1/a/g’ file
  2. 123123
  3. 456a
  4. 789
復(fù)制代碼
改例子使用了一個(gè)正則表達(dá)式/6/去限制替換命令的使用,也就是說(shuō)只有匹配6的行才能夠執(zhí)行替換。
24.        在不含6的行中把所有1都替換成6
  1. #sed ‘/6/!s/1/a/g’ file
  2. a23a23
  3. 4561
  4. 789
復(fù)制代碼
Sed可以使用反向匹配,也就是不匹配的行執(zhí)行動(dòng)作,在這里,不匹配6的第一行中的1都被換成了a,第二行中有6,所以不把1換成a
25.        替換1或者6或者9為a
  1. #sed ‘s/1/a/g;s/6/a/g;s/9/a/g’ file
  2. a23a23
  3. 45aa
  4. 78a
復(fù)制代碼
這里使用了3個(gè)s替換語(yǔ)句去匹配和替換。如果你用的是gnu版本的sed,就可以用下面的語(yǔ)句
  1. #sed ‘s/1|6|9/a/g’ file
  2. a23a23
  3. 45aa
  4. 78a
復(fù)制代碼
Sed提供了更高級(jí)的正則表達(dá)式功能包含了間隔符|,這里的1\|6\|9就是表示匹配1或者6或者9
26.        倒序文本(類(lèi)似tac的作用)
  1. #more file
  2. 123
  3. 456
  4. 789
  5. #sed ‘1!G;h;$!d’ file
  6. 789
  7. 456
  8. 123
復(fù)制代碼
終于到了一個(gè)稍微有點(diǎn)難度的例子了,首先我們來(lái)解釋一個(gè)這個(gè)命令,G:前面講過(guò),就是把緩沖區(qū)的內(nèi)容附加在模式空間的后面(以\n分隔)。h:將模式空間的內(nèi)容把緩沖區(qū)的內(nèi)容覆蓋,這時(shí)候緩沖區(qū)的內(nèi)容和模式空間一樣了d:當(dāng)然就是把模式空間的內(nèi)容刪除,并返回到開(kāi)頭。我們來(lái)逐行看一下
第一行:1!G的意思是出了第一行其他行都執(zhí)行G,因此跳過(guò),直接到h,把模式空間的內(nèi)容拷到緩沖區(qū)中,緩沖區(qū)中的內(nèi)容是123接著執(zhí)行d,返回到了開(kāi)頭,繼續(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ū)通過(guò)h也變成了789\n456\n123,最后的$!d的意思是最后一行不執(zhí)行d的動(dòng)作,也就是命令到此結(jié)束了,sed默認(rèn)把模式空間的789\n456\n123打印出來(lái),也就是大家看到的結(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
最后打印出來(lái)的789\n456\n123也就是我們要的結(jié)果了。
另一種寫(xiě)法
  1. # sed -n '1!G;h;$p' file
  2. 789
  3. 456
  4. 123
復(fù)制代碼
-n防止sed默認(rèn)的p動(dòng)作,而只在最后一行的時(shí)候把模式空間的東西打印出來(lái)
指的一提的是,這個(gè)例子會(huì)在執(zhí)行的過(guò)程中會(huì)使用大量的內(nèi)存,因?yàn)樗诖蛴〕龅剐虻奈谋局鞍颜麄(gè)文件的內(nèi)容都保存在緩沖區(qū)里面,所以如果文件的行數(shù)過(guò)多的話,還是不要使用這個(gè)語(yǔ)句吧。
27.        翻轉(zhuǎn)每行的內(nèi)容(類(lèi)似rev的作用)
  1. # sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//' file
  2. 321
  3. 654
  4. 987
復(fù)制代碼
這個(gè)命令的結(jié)構(gòu)非常復(fù)雜,可以把它分成4個(gè)部分
  1. #sed '
  2. /\n/!G
  3. s/\(.\)\(.*\n\)/&\2\1/
  4. //D
  5. s/.//
  6. '
復(fù)制代碼
我們一個(gè)個(gè)來(lái)分析,以第一行123為例
/\n/!G:如果模式空間的內(nèi)容不包括\n,把緩沖區(qū)的內(nèi)容附加到模式空間后,以\n分隔,緩沖區(qū)的內(nèi)容為空除非有命令對(duì)其進(jìn)行操作,這樣執(zhí)行過(guò)后模式空間的內(nèi)容變成123\n
s/\(.\)\(.*\n\)/&\2\1/:s替換的模式部分包含了2個(gè)字符組,字符組1只包含了1個(gè)任意字符,第二個(gè)字符組包括了剩余的字符和\n,&代表的是前面整個(gè)匹配項(xiàng),也就是123\n,例如,在執(zhí)行完這個(gè)語(yǔ)句后,模式空間的內(nèi)容123\n就變成了123\n23\n1
//D:這個(gè)語(yǔ)句是整個(gè)sed例子的關(guān)鍵,一個(gè)空的匹配//,表示匹配上一個(gè)出現(xiàn)的正則表達(dá)式,這里也就是/\(.\)\(.*\n\)/D了,D的作用是刪除模式空間中從開(kāi)始到第一個(gè)\n截止的字符,并從第一個(gè)命令開(kāi)始重新執(zhí)行sed(不讀到下一行)。實(shí)際上是創(chuàng)建了一個(gè)循環(huán),也就是只要模式空間的\n前面有一個(gè)字符,就把\n和前面的字符刪除,剩余的內(nèi)容傳遞到第一個(gè)命令繼續(xù)執(zhí)行,只有\(zhòng)n前面沒(méi)有字符了,循環(huán)才結(jié)束。
S/.//:意思很簡(jiǎn)單,刪除模式空間的第一個(gè)字符,但是這個(gè)命令執(zhí)行的條件就是D不執(zhí)行,也就是說(shuō)模式空間中\(zhòng)n前面沒(méi)有字符,后面后經(jīng)過(guò)翻轉(zhuǎn)后的內(nèi)容,其實(shí)就是把\n給刪除了,接著默認(rèn)sed輸出翻轉(zhuǎn)后的內(nèi)容,還是來(lái)看一下流程吧
讀入文本                 命令                    模式空間               緩沖空間                  打印結(jié)果
123                    /\n/!G                         123\n                            空                              空
               s/\(.\)\(.*\n\)/&\2\1/          123\n23\n1                                          空
                  //D                           23\n1                           空                             空
        D執(zhí)行成功,循環(huán)到開(kāi)頭執(zhí)行/\n/!G                       
                  /\n/!G                                23\n1            空                            空
        s/\(.\)\(.*\n\)/&\2\1/                              23\n3\n21            空                              空
                  //D                               3\n21           空                              空
        D執(zhí)行成功,循環(huán)到開(kāi)頭執(zhí)行/\n/!G
                    /\n/!G                                 3\n21           空                               空
         s/\(.\)\(.*\n\)/&\2\1/            3\n\n321           空                               空
                        //D                                \n321          空                               空
            D執(zhí)行成功,循環(huán)到開(kāi)頭執(zhí)行/\n/!G               
                         /\n/!G              \n321                          空                                空
                   s/\(.\)\(.*\n\)/&\2\1        \n321          空                               空
                             //D                 \n321          空                                空
        模式不匹配,開(kāi)始執(zhí)行s/.//                   321        空                               321
把321打印出來(lái)了,累死我了。。
28.        把文本兩行合成一行
  1. #more file
  2. 123
  3. 456
  4. 789
  5. abc
  6. #sed ‘$!N;s/\n/ /’ file
  7. 123 456
  8. 789 abc
復(fù)制代碼
這個(gè)例子使用N將兩個(gè)連續(xù)的行組合成一個(gè)新行,他們之間通過(guò)\n連接,因此第二個(gè)替換語(yǔ)句將\n換成空格,就得到了輸出,由于最后一行沒(méi)有下一行可以連接,所以N的前面是$!
29.        如果行的結(jié)尾是\,就把下一行附加到這一行末尾。
  1. #more file
  2. 123\
  3. 456\
  4. 789
  5. abc
  6. #sed –e :a–e ‘/\\$/N;s/\\\n/ /;ta’
  7. 123 456 789
  8. 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:如果沒(méi)有這個(gè)循環(huán)的話,就不能檢查每一行的結(jié)尾是否是\.
30.        如果行的開(kāi)頭是=,就把這行附加到上一行的結(jié)尾。
  1. #more file
  2. 123
  3. =456
  4. =789
  5. abc
復(fù)制代碼
  1. #sed –e :a –e ‘$!N;s/\n=/ /;ta’ –e ‘P;D’ file
  2. 123 456 789
  3. abc
復(fù)制代碼
這個(gè)例子的開(kāi)頭也創(chuàng)建了一個(gè)標(biāo)簽a,然后檢測(cè)文本是不是最后一行,如果不是就把下一行附加到這一行的結(jié)尾,以\n分隔,如果正好下一行的開(kāi)頭是=,則使用替換命令s把換行符\n和=替換成一個(gè)空格,如果替換成功,則ta把命令循環(huán)至標(biāo)簽a的位置,然后繼續(xù)附加下一行,檢查下一行是否是以=開(kāi)頭,是的話就替換,依次循環(huán),知道下一行的開(kāi)頭不是=,則循環(huán)結(jié)束,開(kāi)始執(zhí)行后面的命令P;D,P的意思是打印模式空間中從一個(gè)字符到第一個(gè)\n為止的所有字符,D的意思是刪除第一個(gè)字符到\n截止的所以字符,其實(shí)也就是刪除剛才打印過(guò)的字符,然后回到開(kāi)頭。繼續(xù)讀下一行
        上面的例子中,第一行和第二行第三行之所以連在了一起,就是因?yàn)榈诙泻偷谌惺且?開(kāi)頭。
31.        將數(shù)字組以千分位的方式分成串
  1. #echo "1234567"|sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta'
  2. 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)開(kāi)始,知道所有的數(shù)字都3個(gè)一組的被逗號(hào)分隔。
   看看上面的例子,第二個(gè)組里包含的是數(shù)字1234,第二個(gè)組里包含的是567,加上逗號(hào)后變成1234,567
由于替換成功,循環(huán)開(kāi)始,這次第一個(gè)組里包含的是1,第二個(gè)組里包含的是234,替換過(guò)后,1234,567就變成了1,234,567,接著循環(huán),由于1,234,567中沒(méi)有連續(xù)的四個(gè)數(shù)字,所有替換不成立,sed默認(rèn)打印出模式空間的內(nèi)容,也就是1,234,567。
  如果sed的版本是gnu的,則可以簡(jiǎn)寫(xiě)成
  1. #echo "1234567"|sed ':a;s/\B[0-9]\{3\}\>/,&/;ta'
  2. 1,234,567
復(fù)制代碼
不同的地方在于包含3個(gè)數(shù)字的字符組是如何匹配的。重點(diǎn)在于這個(gè)\B,它是一個(gè)位置字符,不占空間,匹配任何地方但是不包含字符分界線如空格,分號(hào),逗號(hào),冒號(hào)等而最后的\>,匹配的是單詞的分界如逗號(hào)。

32.        每2行加一個(gè)空行
  1. #more file
  2. 123
  3. 456
  4. 789
  5. abc
  6. #sed ‘n;G’ file
  7. 123
  8. 456

  9. 789
  10. abc
復(fù)制代碼
前講過(guò),n命令的作用是打印當(dāng)前行,然后清空,把下一行讀入,G把一個(gè)空行加到了下一行的結(jié)尾,這樣也就是打印了兩行之后在打印一個(gè)空行了。
GNU版本的sed還有另一種寫(xiě)法
  1. #sed ‘0~2G’ file
  2. 123
  3. 456

  4. 789
  5. abc
復(fù)制代碼
這個(gè)其實(shí)也好理解,就是從還沒(méi)有讀入行開(kāi)始,也就是0行,每過(guò)兩行就執(zhí)行一個(gè)G,也就是添加一個(gè)空行,大家記住這個(gè)格式就可以了。
好了第一部分完成了,加油!
作者: Shell_HAT    時(shí)間: 2010-03-15 14:26
感謝分享
作者: bbgg1983    時(shí)間: 2010-03-15 17:03
兄弟,我想看看AWK one-line,給個(gè)鏈接?
作者: where27    時(shí)間: 2010-03-15 19:29
回復(fù) 3# bbgg1983


    http://72891.cn/thread-1640657-1-1.html
作者: yinyuemi    時(shí)間: 2011-04-12 14:38
頂下老表兄的帖子,寫(xiě)得很精彩
作者: linzhiyue    時(shí)間: 2011-06-03 17:26
學(xué)習(xí)了。謝謝樓主豐富且實(shí)用的資料
作者: bbgg1983    時(shí)間: 2011-06-03 22:41
一年前的日子了。。
作者: zhaoke0128    時(shí)間: 2011-06-04 16:27
不錯(cuò),收了
作者: guitor    時(shí)間: 2011-06-04 22:56
學(xué)習(xí)了,找到想要的答案了,非常感謝
作者: zzy7186    時(shí)間: 2011-06-04 23:23
謝lz 學(xué)習(xí)了 寫(xiě)的很詳細(xì) 頂起




歡迎光臨 Chinaunix (http://72891.cn/) Powered by Discuz! X3.2