第一部分: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樣式文件,並據此在原文件的基礎上,插入一些樣式,使其能高亮顯示)
原始的顯示效果:
高亮後的顯示效果:
做者:Viidiot(阿呆) 微信公衆號:linux-code
本文連接:http://www.cnblogs.com/jjdiaries/p/3377875.html
轉載請保留做者及連接