Sed命令詳解及應用實例

第一部分:Sed基本用法css

sed是非交互式的編輯器。它不會修改文件,除非使用shell重定向來保存結果。默認狀況下,全部的輸出行都被打印到屏幕上。html

sed編輯器逐行處理文件(或輸入),並將結果發送到屏幕。具體過程以下:首先sed把當前正在處理的行保存在一個臨時緩存區中(也稱爲模式空間),而後處理臨時緩衝區中的行,完成後把該行發送到屏幕上。sed每處理完一行就將其從臨時緩衝區刪除,而後將下一行讀入,進行處理和顯示。處理完輸入文件的最後一行後,sed便結束運行。sed把每一行都存在臨時緩衝區中,對這個副本進行編輯,因此不會修改原文件。下面先來預覽下sed的經常使用命令及參數。linux

1. p命令.c++

p命令用於輸出匹配行的內容,好比test.txt文件的內容以下,後續說明均已此文件內容來加以說明shell

viidiot@ubuntu:~/Desktop$ cat test.txtubuntu

line one瀏覽器

line two緩存

Hi,everybody,i'm linux-code!微信

   Linux-code,to be the best one!編輯器


單純的p命令會輸出以下,即含有Hi的行被輸出了兩次。

viidiot@ubuntu:~/Desktop$ sed '/Hi/p' test.txt

line one

line two

Hi,everybody,i'm linux-code!

Hi,everybody,i'm linux-code!

   Linux-code,to be the best one!


若是在p命令的基礎上,加上-n選項,能夠輸出含有特定模式的行,以下命令則輸出test.txt文件中含有模式Hi的行。

viidiot@ubuntu:~/Desktop$ sed -n '/Hi/p' test.txt

Hi,everybody,i'm linux-code!

2. d命令

d命令用於刪除特定行。

好比要刪除test.txt中第一二行,其命令以下:

viidiot@ubuntu:~/Desktop$ sed '1,2d' test.txt

Hi,everybody,i'm linux-code!

   Linux-code,to be the best one!


若要刪除最後一行,命令以下:

viidiot@ubuntu:~/Desktop$ sed '$d' test.txt

line one

line two

Hi,everybody,i'm linux-code!


同理,刪除含有linux-code的行:

viidiot@ubuntu:~/Desktop$ sed '/linux-code/d' test.txt

line one

line two

   Linux-code,to be the best one!


3. S命令

s命令用於文本替換。

好比,要將test.txt文件中的Linux-code替換成Viidiot

viidiot@ubuntu:~/Desktop$ sed 's/Linux-code/Viidiot/g' test.txt

line one

line two

Hi,everybody,i'm linux-code!

   Viidiot,to be the best one!

注意後面那個g參數。g表示屢次匹配,若是不加g參數,若某一行有多個匹配在字符串,只替換掉第一次匹配的。


替換以line開頭的行第一個單詞替換爲linux-code

viidiot@ubuntu:~/Desktop$ sed 's/^line/linux-code/' test.txt

linux-code one

linux-code two

   Hi,everybody,i'm linux-code!linux-code!

   Linux-code,to be the best one!


替換以line開頭的行最後一個單詞替換爲linux-code

viidiot@ubuntu:~/Desktop$ sed 's/one$/linux-code/' test.txt

line linux-code

line two

   Hi,everybody,i'm linux-code!linux-code!

   Linux-code,to be the best one!


若是須要將以line開頭的行所有替換掉,而不是僅僅替換掉一個單詞怎麼作呢?後面接.*表示通配的意思,也即^line.*表示以line開頭,後接0個或多個任意字符。

viidiot@ubuntu:~/Desktop$ sed 's/^line.*/linux-code/' test.txt

linux-code

linux-code

   Hi,everybody,i'm linux-code!linux-code!

   Linux-code,to be the best one!


4. e選項

-e即edit的意思,編輯命令,用於sed執行多個編輯任務的狀況下。在下一行開始編輯前,全部的編輯動做將應用到模式緩衝區中的行上。

viidiot@ubuntu:~/Desktop$ sed -e '1,2d' -e 's/linux-code/Linux/' test.txt

   Hi,everybody,i'm Linux!linux-code!

   Linux-code,to be the best one!

上述爲sed命令使用選項-e進行多重編輯後獲得的結果。第一重編輯刪除第一、2行。第二重編輯將出第一、2行外的全部linux-code替換爲Linux。由於是逐行進行這兩項編輯(即這兩個命令都在模式空間的當前行上執行),因此編輯命令的順序會影響結果。


5. r命令

r命令是讀命令。sed使用該命令將一個文本文件中的內容加到當前文件的特定位置上。

viidiot@ubuntu:~/Desktop$ sed '/linux-code/r test1.txt' test.txt

line one

line two

   Hi,everybody,i'm linux-code!linux-code!

linux-code

be perfect!

   Linux-code,to be the best one!

上述命令的意思是:若是在文件test.txt的某一行匹配到模式linux-code,就在該行後讀入文件test1.txt的內容。若是包含linux-code的行不止一行,則在出現linux-code的各行後都讀入test1.txt文件的內容。


6. w命令

viidiot@ubuntu:~/Desktop$ sed '/code/w test1.txt' test.txt

上述命令將test.txt文件中包含模式code的行內容寫入到test1.txt。

7. a\命令

a\命令將添加新文本到文件中當前行(即讀入模式緩衝區中的行)的後面。所追加的文本行位於sed命令的下方另起一行。若是要追加的內容超過一行,則每一行都必須以反斜線結束,最後一行除外。最後一行將以引號和文件名結束。

viidiot@ubuntu:~/Desktop$ cat test1.txt

   Hi,everybody,i'm linux-code!linux-code!

   Linux-code,to be the best one!

經過a\命令將含有模式everybody的行後面加入一行:why ?

viidiot@ubuntu:~/Desktop$ sed '/everybody/a\ why ?' test1.txt

   Hi,everybody,i'm linux-code!linux-code!

why ?

   Linux-code,to be the best one!


8.i\命令

i\命令與a\命令相反,它是在匹配行的前面插入一行。

viidiot@ubuntu:~/Desktop$ sed '/everybody/i\ you are beautiful' test1.txt

you are beautiful

   Hi,everybody,i'm linux-code!linux-code!

   Linux-code,to be the best one!


9. c\命令

c\命令將匹配行修改爲咱們設定的內容。以下則將test1.txt中含有everybody的行修改成you are beautiful

viidiot@ubuntu:~/Desktop$ sed '/everybody/c\ you are beautiful' test1.txt

you are beautiful

   Linux-code,to be the best one!

10. y命令

y命令與UNIX/Linux中的tr命令相似,字符按照一對一的方式從左到右進行轉換。例如,y/abc/ABC/將把全部小寫的a轉換成A,小寫的b轉換成B,小寫的c轉換成C。

viidiot@ubuntu:~/Desktop$ sed 'y/code/CODE/' test1.txt

   Hi,EvErybODy,i'm linux-CODE!linux-CODE!

   Linux-CODE,tO bE thE bEst OnE!

將對應小寫字母所有替換成其大寫字母。


第二部分:Sed腳本

經過編寫腳本咱們能夠方便的批量執行命令。sed腳本就是寫在文件中的一系列sed命令。sed腳本中,要求命令的末尾不能有任何多餘的空格或文本。若是在一行中有多個命令,要用分號分隔。執行腳本 時,sed先將輸入文件中第一行復制到模式緩衝區,而後對其執行腳本中全部的命令。每一行處理完畢後,sed再複製文件中下一行到模式緩衝區,對其執行腳 本中全部命令。使用sed腳本時,再也不用引號來確保sed命令不被shell解釋。

舉例:咱們如今來完成以下任務

在test1.txt中的開頭插入一行歡迎詞:Welcome to linux-code

在末尾加入一行:good bye!

將文章中全部code替換成CODE。

那麼咱們能夠編寫一個名爲sedscript腳本,腳本具體內容以下:

viidiot@ubuntu:~/Desktop$ cat sedscript

1i\Welcome to linux-code

s/code/CODE/g

$a\goodbye!

而後再將sed腳本應用到test1.txt文件上

viidiot@ubuntu:~/Desktop$ sed -f sedscript test1.txt

Welcome to linux-code

   Hi,everybody,i'm linux-CODE!linux-CODE!

   Linux-CODE,to be the best one!

goodbye!

第三部分:練習題

學習了sed的基本知識,如今咱們來檢驗下成果吧!呵呵。。。

一、Sed中如何替換多行中的有規律的數字字符串 

輸入:

hello world balabala - . gene_id "240838 "; transcript_id "240838";

hello world balabala again - . gene_id "240838 "; transcript_id "240838";

balaba….

輸出:

hello world balabala - . gene_id "zgg240838 "; transcript_id "zgg240838";

hello world balabala again - . gene_id "zgg240838 "; transcript_id "zgg240838";

balaba…

也即,將字符gene_id「後接數字以及transcript_id "後接數字中的引號與數字之間插入zgg字符串。

腳本編寫:

 sed  's/gene_id "\([0-9]\+\)"; transcript_id "\([0-9]\+\)";/gene_id "zgg\1"; transcript_id "zgg\2";/g' test.txt

注:1. 數字的匹配[0-9]

2.[0-9]後接\+表示匹配一個或多個數字

3.匹配部分加括號,引用匹配部分用\1,\2,....等等。

4.sed執行多個匹配用分號鏈接,整個命令用’’引在內部。

二、在文本中每一行添加行頭行尾

好比test.txt 內容以下所示:

viidiot@ubuntu:~/Desktop$ cat test.txt

line one

line two

line three

line four

1)在每行文字開頭添加文字「Viidiot 」:

viidiot@ubuntu:~/Desktop$ sed '/./s/^/Viidiot /g' test.txt

Viidiot line one

Viidiot line two

Viidiot line three

Viidiot line four

2)末尾添加文字「 Viidiot」:

viidiot@ubuntu:~/Desktop$ sed '/./s/$/ Viidiot/g' test.txt

line one Viidiot

line two Viidiot

line three Viidiot

line four Viidiot

三、利用sed進行格式轉換

好比須要將text.txt中以下內容

   dn: uid=admin,ou=ITaccounts,dc=tc
   uid: admin
   cn: admin cn
   sn: admin sn


   dn: uid=0037,ou=employees,dc=tci
   uid: 0037
   cn: thinker
   sn: zzz


轉換成xml格式以下:
   <entity>
   <dn>uid=admin,ou=ITaccounts,dc=tc</dn>
     <uid>admin</uid>
     <cn>admin cn</cn>
   <sn>admin sn</sn>
   </entity>
   <entity>
   <dn>uid=0037,ou=employees,dc=tci</dn>
     <uid>0037</uid>
     <cn>thinker</cn>
     <sn>zzz</sn>
     </entity>


則能夠定義下面的sedscript文件:
/^dn:[[:space:]]/i\
<entity>
s/^dn:[[:space:]]\(.*\)$/<dn>\1<\/dn>/g
s/^uid:[[:space:]]\(.*\)$/<uid>\1<\/uid>/g
s/^cn:[[:space:]]\(.*\)$/<cn>\1<\/cn>/g
s/^sn:[[:space:]]\(.*\)$/<sn>\1<\/sn>/g
s/^$/<\/entity>/g
第一行和第二行實現的功能就是在每一個dn:開頭的行前面加上一行<entity>。最後一行是碰到空行補上</entity>這 個結束標記。

另外,在執行替換的時候能夠經過使用\(\)把被替換的字符串分組,在替換的部分裏面用\一、\2這種方式引用被替換文字裏面的相應的組。

用這種方法把ldif文件裏面[:]前的東西刪掉而且在兩邊增長相應的xml標記。
仔細想一想,4行替換也許用下面的1行就能實現?
s/^\(.*\):[[:space:]]\(.*\)$/<\1>\2<\/\1>/g

viidiot@ubuntu:~/Desktop$ sed -f sedscript test.txt

<entity>

<dn>uid=admin,ou=ITaccounts,dc=tc</dn>

<uid>admin</uid>

<cn>admin cn</cn>

<sn>admin sn</sn>

<entity>

<dn>uid=0037,ou=employees,dc=tci</dn>

<uid>0037</uid>

<cn>thinker</cn>

<sn>zzz</sn>


四、在匹配的行前面插入一行

viidiot@ubuntu:~/Desktop$ cat test.txt

line one

line two

Hi,everybody,i'm linux-code!

   Linux-code,to be the best one!

將以空格開頭的行前面插入一行文字:a new paragraph

viidiot@ubuntu:~/Desktop$ sed '/^[[:space:]]/i   a new paragraph'  test.txt

line one

line two

a new paragraph

Hi,everybody,i'm linux-code!

a new paragraph

   Linux-code,to be the best one!


五、在文章中每一行前加上行號

此題是由sed引入的題外話。用sed怎麼去完成?讀者本身開動開動腦筋吧!

在文章中每一行加上行號的方法有不少,好比,咱們能夠這樣:

viidiot@ubuntu:~/Desktop$ nl test.txt

     1 line one

     2 line two

     3 Hi,everybody,i'm linux-code!

     4    Linux-code,to be the best one!

也能夠這樣:

viidiot@ubuntu:~/Desktop$ cat -n test.txt

     1 line one

     2 line two

     3 Hi,everybody,i'm linux-code!

     4    Linux-code,to be the best one!

還能夠這樣:

viidiot@ubuntu:~/Desktop$ awk '{print NR, $0}' test.txt

1 line one

2 line two

3  Hi,everybody,i'm linux-code!

4    Linux-code,to be the best one!

因此,若是須要在文本test.txt中永久的插入行號並存檔,你也行能夠這樣:

viidiot@ubuntu:~/Desktop$ cat -n test.txt >>tmp.txt;mv tmp.txt test.txt

viidiot@ubuntu:~/Desktop$ cat test.txt

     1 line one

     2 line two

     3 Hi,everybody,i'm linux-code!

     4    Linux-code,to be the best one!


本文就這麼多了,最後留下一個實踐內容,編寫一個名叫highlightcode.sh程序,將一個原始的c程序,用sed將它進行格式化,使其可以高亮顯示關鍵字。固然,你能夠用純c/c++去完成這個功能,但腳本可能能夠更快的編寫出來(相對於c程序)。(注:高亮是指其在瀏覽器中顯示的效果。這裏牽涉到css樣式文件,並據此在原文件的基礎上,插入一些樣式,使其能高亮顯示)

原始的顯示效果:

image

高亮後的顯示效果:

image

做者:Viidiot(阿呆) 微信公衆號:linux-code

本文連接:http://www.cnblogs.com/jjdiaries/p/3377875.html

轉載請保留做者及連接

相關文章
相關標籤/搜索