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

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫(kù)
最近訪問板塊 發(fā)新帖
查看: 7898 | 回復(fù): 9
打印 上一主題 下一主題

Famous Sed One-Liners Explained中文版 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2010-03-15 14:09 |只看該作者 |倒序?yàn)g覽
本帖最后由 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è)例子說明吧
  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類似,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.        輸出兩倍行距文件
  1. #sed ‘G’ file
  2. 123

  3. 456
復(fù)制代碼
這個(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è)空行)
  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)作}語句,第一個(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被行距
  1. #sed ‘G;G’ file
復(fù)制代碼
這個(gè)沒什么好講的,兩次G,也就是附加兩個(gè)回車在文本的后面,打印出來。
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)容,在回到開頭。所以大家可以發(fā)現(xiàn),打印出來的都是奇數(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)打印出來而已,當(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è)空行
  1. #sed ‘/5/G’ file
  2. 123
  3. 456

  4. 789
復(fù)制代碼
這個(gè)例子和第一個(gè)例子類似,只不過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è)語句其實(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í)行的過程
  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è)語句是針對(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)容
  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把沒兩行的內(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,用-來代替空格。
  1. # echo "-----12@contents" | sed 's/-*\(.\{6,\}\)@/\1--/'
  2. ----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)
  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è)部分,第一部分的輸出通過管道符|傳遞給第二部分當(dāng)做第二部分的輸入,第一部分使用正則表達(dá)式/./過濾出至少一個(gè)字符的行,當(dāng)sed把空行放入模式空間后,由于不匹配模式,因此也不對(duì)其執(zhí)行=這個(gè)編號(hào)的命令。第二部分和第八例題一樣也是把兩行合并成一行后,替換\n為空格,然后打印出來。
11.        計(jì)算文件的行數(shù)(類似wc –l的作用)
  1. #sed -n '$=' file
  2. 4
復(fù)制代碼
這個(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.        刪除每行的空白符(包括空格和制表符)
  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è)也沒什么好講的,匹配行尾有任意個(gè)空白的行,并把空白刪除
14.        同時(shí)刪除行首和行尾的空白
  1. # sed 's/^[ \t]*//;s/[ \t]*$//' file
復(fù)制代碼
只是兩個(gè)例子的合體而已。

15.        每行的開頭添加兩個(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把一段語句分成若干部分,當(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)
  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)單的替換語句,把文本中每行的第一個(gè)1替換成a
19.        替換每行出現(xiàn)的第二個(gè)1為a
  1. #sed ‘s/1/a/2’ file
  2. 123a23123
  3. 456
  4. 789
復(fù)制代碼
其實(shí)這才是替換語句的完成格式,把每行中出現(xiàn)的第二個(gè)1替換成a,沒有這個(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替換語句中出現(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
  1. #sed ‘s/\(.*\)1/a/’ file
  2. 123a23
  3. 4561
  4. 789
復(fù)制代碼
同樣使用了字符組,匹配的是1前面的所有字符,之所以會(huì)把最后出現(xiàn)的1替換成a,是因?yàn)?*是最大匹配,比如說在第一行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/去限制替換命令的使用,也就是說只有匹配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替換語句去匹配和替換。如果你用的是gnu版本的sed,就可以用下面的語句
  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.        倒序文本(類似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)難度的例子了,首先我們來解釋一個(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é)果了。
另一種寫法
  1. # sed -n '1!G;h;$p' file
  2. 789
  3. 456
  4. 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的作用)
  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è)來分析,以第一行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.        把文本兩行合成一行
  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è)新行,他們之間通過\n連接,因此第二個(gè)替換語句將\n換成空格,就得到了輸出,由于最后一行沒有下一行可以連接,所以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:如果沒有這個(gè)循環(huán)的話,就不能檢查每一行的結(jié)尾是否是\.
30.        如果行的開頭是=,就把這行附加到上一行的結(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è)例子的開頭也創(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ù)字組以千分位的方式分成串
  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)開始,知道所有的數(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)寫成
  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ù)制代碼
前講過,n命令的作用是打印當(dāng)前行,然后清空,把下一行讀入,G把一個(gè)空行加到了下一行的結(jié)尾,這樣也就是打印了兩行之后在打印一個(gè)空行了。
GNU版本的sed還有另一種寫法
  1. #sed ‘0~2G’ file
  2. 123
  3. 456

  4. 789
  5. abc
復(fù)制代碼
這個(gè)其實(shí)也好理解,就是從還沒有讀入行開始,也就是0行,每過兩行就執(zhí)行一個(gè)G,也就是添加一個(gè)空行,大家記住這個(gè)格式就可以了。
好了第一部分完成了,加油!

論壇徽章:
33
ChinaUnix元老
日期:2015-02-02 08:55:39CU十四周年紀(jì)念徽章
日期:2019-08-20 08:30:3720周年集字徽章-周	
日期:2020-10-28 14:13:3020周年集字徽章-20	
日期:2020-10-28 14:04:3019周年集字徽章-CU
日期:2019-09-08 23:26:2519周年集字徽章-19
日期:2019-08-27 13:31:262016科比退役紀(jì)念章
日期:2022-04-24 14:33:24
2 [報(bào)告]
發(fā)表于 2010-03-15 14:26 |只看該作者
感謝分享

論壇徽章:
0
3 [報(bào)告]
發(fā)表于 2010-03-15 17:03 |只看該作者
兄弟,我想看看AWK one-line,給個(gè)鏈接?

論壇徽章:
0
4 [報(bào)告]
發(fā)表于 2010-03-15 19:29 |只看該作者
回復(fù) 3# bbgg1983


    http://www.72891.cn/thread-1640657-1-1.html

論壇徽章:
2
射手座
日期:2014-10-10 15:59:4715-16賽季CBA聯(lián)賽之上海
日期:2016-03-03 10:27:14
5 [報(bào)告]
發(fā)表于 2011-04-12 14:38 |只看該作者
頂下老表兄的帖子,寫得很精彩

論壇徽章:
0
6 [報(bào)告]
發(fā)表于 2011-06-03 17:26 |只看該作者
學(xué)習(xí)了。謝謝樓主豐富且實(shí)用的資料

論壇徽章:
0
7 [報(bào)告]
發(fā)表于 2011-06-03 22:41 |只看該作者
一年前的日子了。。

論壇徽章:
0
8 [報(bào)告]
發(fā)表于 2011-06-04 16:27 |只看該作者
不錯(cuò),收了

論壇徽章:
0
9 [報(bào)告]
發(fā)表于 2011-06-04 22:56 |只看該作者
學(xué)習(xí)了,找到想要的答案了,非常感謝

論壇徽章:
0
10 [報(bào)告]
發(fā)表于 2011-06-04 23:23 |只看該作者
謝lz 學(xué)習(xí)了 寫的很詳細(xì) 頂起
您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國(guó)互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP