本文承接以前寫的三十分鐘學會AWK一文,在學習完AWK以後,趁熱打鐵又學習了一下SED,不得不說這兩個工具真的堪稱文本處理神器,誰用誰知道!本文大部份內容依舊是翻譯自Tutorialspoint上的入門教程,此次是 Sed Tutorial 一文,內容作了一些刪減和補充,增長了一些原文中沒有說起到的語法和命令的講解,而且對原文全部的示例都一一進行了驗證,但願本文對你們學習和了解Sed有所幫助。javascript
文中用到的測試文件能夠在 https://github.com/mylxsw/sed-demo找到。css
本文將會持續修正和更新,最新內容請參考個人 GITHUB 上的 程序猿成長計劃 項目,歡迎 Star。html
概述
SED的英文全稱是 Stream EDitor,它是一個簡單而強大的文本解析轉換工具,在1973-1974年期間由貝爾實驗室的Lee E. McMahon開發,今天,它已經運行在全部的主流操做系統上了。java
McMahon建立了一個通用的行編輯器,最終變成爲了SED。SED的不少語法和特性都借鑑了ed編輯器。設計之初,它就已經支持正則表達式,SED能夠從文件中接受相似於管道的輸入,也能夠接受來自標準輸入流的輸入。ios
SED由自由軟件基金組織(FSF)開發和維護而且隨着GNU/Linux進行分發,所以,一般它也稱做 GNU SED。對於新手來講,SED的語法看起來可能有些神祕,可是,一旦掌握了它的語法,你就能夠只用幾行代碼去解決很是複雜的任務,這就是SED的魅力所在。nginx
SED的典型用途
SED的用途很是普遍,例如:git
文本替換github
選擇性的輸出文本文件正則表達式
從文本文件的某處開始編輯sql
無交互式的對文本文件進行編輯等
工做流
在本章中,咱們將會探索SED是如何工做的,要想成爲一個SED專家,你須要知道它的內部實現。SED遵循簡單的工做流:讀取,執行和顯示,下圖描述了該工做流:
讀取: SED從輸入流(文件,管道或者標準輸入)中讀取一行而且存儲到它叫作 模式空間(pattern buffer) 的內部緩衝區
執行: 默認狀況下,全部的SED命令都在模式空間中順序的執行,除非指定了行的地址,不然SED命令將會在全部的行上依次執行
顯示: 發送修改後的內容到輸出流。在發送數據以後,模式空間將會被清空。
在文件全部的內容都被處理完成以前,上述過程將會重複執行
須要注意的幾點
模式空間 (pattern buffer) 是一塊活躍的緩衝區,在sed編輯器執行命令時它會保存待檢查的文本
默認狀況下,全部的SED命令都是在模式空間中執行,所以輸入文件並不會發生改變
還有另一個緩衝區叫作 保持空間 (hold buffer),在處理模式空間中的某些行時,能夠用保持空間來臨時保存一些行。在每個循環結束的時候,SED將會移除模式空間中的內容,可是該緩衝區中的內容在全部的循環過程當中是持久存儲的。SED命令沒法直接在該緩衝區中執行,所以SED容許數據在 保持空間 和 模式空間之間切換
初始狀況下,保持空間 和 模式空間 這兩個緩衝區都是空的
若是沒有提供輸入文件的話,SED將會從標準輸入接收請求
若是沒有提供地址範圍的話,默認狀況下SED將會對全部的行進行操做
示例
讓咱們建立一個名爲 quote.txt 的文本文件,文件內容爲著名做家Paulo Coelho的一段名言
$ vi quote.txt
There is only one thing that makes a dream impossible to achieve: the fear of failure.
- Paulo Coelho, The Alchemist
爲了理解SED的工做流,咱們首先使用SED顯示出quote.txt文件的內容,該示例與cat
命令相似
$ sed '' quote.txt
There is only one thing that makes a dream impossible to achieve: the fear of failure.
- Paulo Coelho, The Alchemist
在上面的例子中,quote.txt是輸入的文件名稱,兩個單引號是要執行的SED命令。
首先,SED將會讀取quote.txt文件中的一行內容存儲到它的模式空間中,而後會在該緩衝區中執行SED命令。在這裏,沒有提供SED命令,所以對該緩衝區沒有要執行的操做,最後它會刪除模式空間中的內容而且打印該內容到標準輸出,很簡單的過程,對吧?
在下面的例子中,SED會從標準輸入流接受輸入
$ sed ''
當上述命令被執行的時候,將會產生下列結果
There is only one thing that makes a dream impossible to achieve: the fear of failure.
There is only one thing that makes a dream impossible to achieve: the fear of failure.
在這裏,第一行內容是經過鍵盤輸入的內容,第二行是SED輸出的內容。
從SED會話中退出,使用組合鍵
ctrl-D (^D)
基礎語法
本章中將會介紹SED中的基本命令和它的命令行使用方法。SED能夠用下列兩種方式調用:
sed [-n] [-e] 'command(s)' files
sed [-n] -f scriptfile files
第一種方式在命令行中使用單引號指定要執行的命令,第二種方式則指定了包含SED命令的腳本文件。固然,這兩種方法也能夠同時使用,SED提供了不少參數用於控制這種行爲。
讓咱們看看如何指定多個SED命令。SED提供了delete
命令用於刪除某些行,這裏讓咱們刪除第一行,第二行和第五行:
首先,使用cat
命令顯示文件內容
$ cat books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
如今,使用SED移除指定的行,爲了刪除三行,咱們使用-e
選項指定三個獨立的命令
$ sed -e '1d' -e '2d' -e '5d' books.txt
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
6) A Game of Thrones, George R. R. Martin, 864
咱們還能夠將多個SED命令寫在一個文本文件中,而後將該文件做爲SED命令的參數,SED能夠對模式空間中的內容執行文件中的每個命令,下面的例子描述了SED的第二種用法
首先,建立一個包含SED命令的文本文件,爲了便於理解,咱們使用與以前相同的SED命令
$ echo -e "1d\n2d\n5d" > commands.txt
$ cat commands.txt
1d
2d
5d
接下來構造一個SED命令去執行該操做
$ sed -f commands.txt books.txt
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
6) A Game of Thrones, George R. R. Martin, 864
標準選項
SED支持下列標準選項:
-
-n 默認狀況下,模式空間中的內容在處理完成後將會打印到標準輸出,該選項用於阻止該行爲
$ sed -n '' quote.txt
-
-e 指定要執行的命令,使用該參數,咱們能夠指定多個命令,讓咱們打印每一行兩次:
$ sed -e '' -e 'p' quote.txt There is only one thing that makes a dream impossible to achieve: the fear of failure. There is only one thing that makes a dream impossible to achieve: the fear of failure.
Paulo Coelho, The Alchemist
Paulo Coelho, The Alchemist
-
-f 指定包含要執行的命令的腳本文件
$ echo "p" > commands $ $ sed -n -f commands quote.txt There is only one thing that makes a dream impossible to achieve: the fear of failure.
Paulo Coelho, The Alchemist
GNU選項
這些選項是GNU規範定義的,可能對於某些版本的SED並不支持。
-n, --quiet, --slient:與標準的-n選項相同
-e script,--expression=script:與標準的-e選項相同
-f script-file, --file=script-file:與標準的-f選項相同
--follow-symlinks:若是提供該選項的話,在編輯的文件是符號連接時,SED將會跟隨連接
-i[SUFFIX],--in-place[=SUFFIX]:該選項用於對當前文件進行編輯,若是提供了SUFFIX的話,將會備份原始文件,不然將會覆蓋原始文件
-l N, --line-lenght=N:該選項用於設置行的長度爲N個字符
--posix:該選項禁用全部的GNU擴展
-r,--regexp-extended:該選項將啓用擴展的正則表達式
-u, --unbuffered:指定該選項的時候,SED將會從輸入文件中加載最少的數據,而且更加頻繁的刷出到輸出緩衝區。在編輯
tail -f
命令的輸出,你不但願等待輸出的時候該選項是很是有用的。-z,--null-data:默認狀況下,SED對每一行使用換行符分割,若是提供了該選項的話,它將使用NULL字符分割行
循環
與其它編程語言相似,SED提供了用於控制執行流的循環和分支語句。
SED中的循環有點相似於goto語句,SED能夠根據標籤(label)跳轉到某一行繼續執行,在SED中,咱們能夠定義以下的標籤:
:label
:start
:end
:up
在上面的示例中,咱們建立了四個標籤。
要跳轉到指定的標籤,使用 b 命令後面跟着標籤名,若是忽略標籤名的話,SED將會跳轉到SED文件的結尾。
b標籤用於無條件的跳轉到指定的label。
爲了更好地理解SED中的循環和分支,讓咱們建立一個名爲books2.txt的文本文件,其中包含一些圖書的標題和做者信息,下面的示例中會合並圖書的標題和做者,使用逗號分隔。以後搜索全部匹配「Paulo」的行,若是匹配的話就在這一行的開頭添加-
,不然跳轉到Print
標籤,打印出該行內容。
$ cat books2.txt
A Storm of Swords
George R. R. Martin
The Two Towers
J. R. R. Tolkien
The Alchemist
Paulo Coelho
The Fellowship of the Ring
J. R. R. Tolkien
The Pilgrimage
Paulo Coelho
A Game of Thrones
George R. R. Martin
$ sed -n ' h;n;H;x s/\n/, / /Paulo/!b Print s/^/- / :Print p' books2.txt
A Storm of Swords , George R. R. Martin
The Two Towers , J. R. R. Tolkien
- The Alchemist , Paulo Coelho
The Fellowship of the Ring , J. R. R. Tolkien
- The Pilgrimage , Paulo Coelho
A Game of Thrones , George R. R. Martin
乍看來上述的代碼很是神祕,讓咱們逐步拆解一下
第一行是
h;n;H;x
這幾個命令,記得上面咱們提到的 保持空間 嗎?第一個h
是指將當前模式空間中的內容覆蓋到 保持空間中,n
用於提早讀取下一行,而且覆蓋當前模式空間中的這一行,H
將當前模式空間中的內容追加到 保持空間 中,最後的x
用於交換模式空間和保持空間中的內容。所以這裏就是指每次讀取兩行放到模式空間中交給下面的命令進行處理接下來是 s/n/, / 用於將上面的兩行內容中的換行符替換爲逗號
第三個命令在不匹配的時候跳轉到Print標籤,不然繼續執行第四個命令
:Print僅僅是一個標籤名,而
p
則是print命令
爲了提升可讀性,每個命令都佔了一行,固然,你也能夠把全部命令放在一行
$ sed -n 'h;n;H;x;s/\n/, /;/Paulo/!b Print; s/^/- /; :Print;p' books2.txt
關於
h
,H
,x
命令參考官方手冊 sed, a stream editor 3.6 Less Frequently-Used Commands節
分支
使用 t 命令建立分支。只有當前置條件成功的時候,t 命令纔會跳轉到該標籤。
t命令只有在前一個替換(s)命令執行成功的時候纔會執行。
讓咱們看一些前面章節中的例子,與以前不一樣的是,此次咱們將打印四個連字符"-",而以前是一個。
$ sed -n '
h;n;H;x
s/\n/, /
:Loop
/Paulo/s/^/-/
/----/!t Loop
p' books2.txt
A Storm of Swords , George R. R. Martin
The Two Towers , J. R. R. Tolkien
----The Alchemist , Paulo Coelho
The Fellowship of the Ring , J. R. R. Tolkien
----The Pilgrimage , Paulo Coelho
A Game of Thrones , George R. R. Martin
在上面的例子中,前面兩行與上一節中講的做用一致,第三行定義了一個Loop標籤,接下來匹配存在「Paulo」的行,若是存在則在最前面添加一個-,接下來是咱們這裏的重點:
/----/!t Loop
這一行首先檢查上面添加-
以後是否知足四個-
,若是不知足則跳轉到Loop繼續執行第三行,這樣不停的追加-
,最後若是改行知足前面有四個-
才繼續往下執行。
爲了提升可讀性,咱們將每個SED命令獨立一行,咱們也能夠在同一行中使用:
sed -n 'h;n;H;x; s/\n/, /; :Loop;/Paulo/s/^/-/; /----/!t Loop; p' books.txt
模式空間和保持空間
模式空間
對任何文件的來講,最基本的操做就是輸出它的內容,爲了實現該目的,在SED中可使用print命令打印出模式空間中的內容。
首先建立一個包含行號,書名,做者和頁碼數的文件,在本文中咱們將會使用該文件,你也能夠建立任何其它的文件,可是這裏咱們就建立一個包含如下內容的文件
$ vi books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho,288
6) A Game of Thrones, George R. R. Martin, 864
執行p
命令
$ sed 'p' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
6) A Game of Thrones, George R. R. Martin, 864
你可能會疑惑,爲何每一行被顯示了兩次?
你還記得SED的工做流嗎?默認狀況下,SED將會輸出模式空間中的內容,另外,咱們的命令中包含了輸出命令p
,所以每一行被打印兩次。可是不要擔憂,SED提供了-n參數用於禁止自動輸出模式空間的每一行的行爲
$ sed -n 'p' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
行尋址
默認狀況下,在SED中使用的命令會做用於文本數據的全部行。若是隻想將命令做用於特定的行或者某些行,則須要使用 行尋址 功能。
在SED中包含兩種形式的行尋址:
以數字形式表示的行區間
以文本模式來過濾行
兩種形式都使用相同的語法格式
[address]command
數字方式的行尋址
在下面的示例中SED只會對第3行進行操做
$ sed -n '3p' books.txt
3) The Alchemist, Paulo Coelho, 197
固然,咱們還可讓SED輸出某些行。在SED中使用逗號,分隔輸出行號的範圍,例以下面的代碼會輸出出2-5行的內容
$ sed -n '2,5 p' books.txt
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
特殊字符 $ 表明了文件的最後一行,輸出文件的最後一行
$ sed -n '$ p' books.txt
6) A Game of Thrones, George R. R. Martin, 864
也可使用 $ 指定輸出的地址範圍,下列命令輸出第三行到最後一行
$ sed -n '3,$ p' books.txt
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho,288
6) A Game of Thrones, George R. R. Martin, 864
SED還提供了另外兩種操做符用於指定地址範圍,第一個是加號(+)操做符,它能夠與逗號(,)操做符一塊兒使用,例如 M, +n
將會打印出從第M
行開始的下n
行。下面的示例將會輸出第二行開始的下面四行
$ sed -n '2,+4 p' books.txt
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
咱們還可使用波浪線操做符(~)指定地址範圍,它使用M~N
的形式,它告訴SED應該處理M
行開始的每N
行。例如,50~5
匹配行號50,55,60,65等,讓咱們只輸出文件中的奇數行
$ sed -n '1~2 p' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
3) The Alchemist, Paulo Coelho, 197
5) The Pilgrimage, Paulo Coelho, 288
下面的代碼則是隻輸出文件中的偶數行
$ sed -n '2~2 p' books.txt
2) The Two Towers, J. R. R. Tolkien, 352
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
6) A Game of Thrones, George R. R. Martin, 864
注意,若是使用的是Mac系統自帶的sed命令,可能不支持~和+操做符。可使用
brew install gnu-sed --with-default-names
從新安裝GNU-SED。
使用文本模式過濾器
SED編輯器容許指定文本模式來過濾出命令要做用的行。格式以下:
/pattern/command
必須用正斜線將要指定的pattern封起來。sed編輯器會將該命令做用到包含指定文本模式的行上。
下面的示例中,將會輸出全部做者爲Paulo Coelho的書籍。
$ sed -n '/Paulo/ p' books.txt
3) The Alchemist, Paulo Coelho, 197
5) The Pilgrimage, Paulo Coelho, 288
模式匹配也能夠與數字形式的尋址同時使用,在下面的示例會從第一次匹配到Alchemist
開始輸出,直到第5行爲止。
$ sed -n '/Alchemist/, 5 p' books.txt
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
使用逗號(,)操做符指定匹配多個匹配的模式。下列的示例將會輸出Two和Pilgrimage之間的全部行
$ sed -n '/Two/, /Pilgrimage/ p' books.txt
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
在使用文本模式過濾器的時候,與數字方式的行尋址相似,可使用加號操做符 +,它會輸出從當前匹配位置開始的某幾行,下面的示例會從第一次Two出現的位置開始輸出接下來的4行
$ sed -n '/Two/, +4 p' books.txt
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
保持空間
在處理模式空間中的某些行時,能夠用保持空間來臨時保存一些行。有5條命令可用來操做保持空間
命令 | 描述 |
---|---|
h | 將模式空間複製到保持空間 |
H | 將模式空間附加到保持空間 |
g | 將保持空間複製到模式空間 |
G | 將保持空間附加到模式空間 |
x | 交換模式空間和保持空間的內容 |
關於保持空間這裏就不在舉例了,前面再循環部分講解下面這個命令的時候咱們已經對它的使用作了說明。
$ sed -n 'h;n;H;x;s/\n/, /;/Paulo/!b Print; s/^/- /; :Print;p' books2.txt
基本命令
本章將會講解一些經常使用的SED命令,主要包括DELETE
,WRITE
,APPEND
,CHANGE
,INSERT
,TRANSLATE
,QUIT
,READ
,EXECUTE
等命令。
刪除命令 d
刪除命令格式以下
[address1[,address2]]d
address1
和address2
是開始和截止地址,它們能夠是行號或者字符串匹配模式,這兩種地址都是可選的。
由命令的名稱能夠知道,delete 命令是用來執行刪除操做的,而且由於SED是基於行的編輯器,所以咱們說該命令是用來刪除行的。注意的是,該命令只會移除模式空間中的行,這樣該行就不會被髮送到輸出流,但原始內容不會改變。
$ sed 'd' books.txt
爲何沒有輸出任何內容?默認狀況下,SED將會對每一行執行刪除操做,這就是該命令爲何沒有在標準輸出中輸出任何內容的緣由。
下列命令只移除第四行
[jerry]$ sed '4d' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
SED也接受使用逗號(,)分隔的地址範圍。咱們能夠構造地址範圍去移除N1到N2行,例如,下列命令將刪除2-4行
$ sed '2, 4 d' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
SED的地址範圍並不只僅限於數字,咱們也能夠指定模式匹配做爲地址,下面的示例會移除全部做者爲Paulo Coelho的書籍
$ sed '/Paulo Coelho/d' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
6) A Game of Thrones, George R. R. Martin, 864
我移除全部以Storm
和Fellowship
開頭的行
$ sed '/Storm/,/Fellowship/d' books.txt
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
文件寫入命令 w
SED提供了 write 命令用於將模式空間中的內容寫入到文件,與 delete 命令相似,下面是 write 命令的語法
[address1[,address2]]w file
w 指定是寫命令, file 指的是存儲文件內容的文件名。使用 file 操做符的時候要當心,當提供了文件名可是文件不存在的時候它會自動建立,若是已經存在的話則會覆蓋原文件的內容。
下面的SED命令會建立文件books.txt的副本,在 w 和 file 之間只能有一個空格
$ sed -n 'w books.bak' books.txt
上述命令建立了一個名爲 books.bak 的文件,驗證一下兩個文件的內容是否相同
$ diff books.txt books.bak
$ echo $?
一旦執行上述的代碼,你將會獲得下列輸出
0
聰明的你可能已經想到了,這不就是 cp 命令作的事情嗎!確實如此,cp 命令也作了同一件事情,可是SED是一個成熟的工具,使用它你能夠只複製文件中的某些行到新的文件中,以下代碼會存儲文件中的奇數行到另外一個文件
$ sed -n '2~2 w junk.txt' books.txt
$ cat junk.txt
2) The Two Towers, J. R. R. Tolkien, 352
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
6) A Game of Thrones, George R. R. Martin, 864
假設你但願存儲全部獨立做者的書到單獨的文件。若是人工去作的話,確定是很是無聊並且沒有技術含量的,可是使用SED,你就有了更加聰明的方法去實現
$ sed -n -e '/Martin/ w Martin.txt' -e '/Paulo/ w Paulo.txt' -e '/Tolkien/ w Tolkien.txt' books.txt
$ cat Martin.txt
1) A Storm of Swords, George R. R. Martin, 1216
6) A Game of Thrones, George R. R. Martin, 864
$ cat Paulo.txt
3) The Alchemist, Paulo Coelho, 197
5) The Pilgrimage, Paulo Coelho, 288
$ cat Tolkien.txt
2) The Two Towers, J. R. R. Tolkien, 352
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
追加命令 a
文本追加命令語法:
[address]a\
Append text
在第四行以後追加一本新書:
$ sed '4 a 7) Adultry, Paulo Coelho, 234' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
7) Adultry, Paulo Coelho, 234
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
在命令部分,4指的是行號,a
是append命令,剩餘部分爲要追加的文本。
在文件的結尾插入一行文本,使用 $ 做爲地址
$ sed '$ a 7) Adultry, Paulo Coelho, 234' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
7) Adultry, Paulo Coelho, 234
除了行號,咱們也可使用文本模式指定地址,例如,在匹配 The Alchemist
的行以後追加文本
$ sed '/The Alchemist/ a 7) Adultry, Paulo Coelho, 234' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
7) Adultry, Paulo Coelho, 234
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
行替換命令 c
SED經過 c 提供了 change 和 replace 命令,該命令幫助咱們使用新文本替換已經存在的行,當提供行的地址範圍時,全部的行都被做爲一組被替換爲單行文本,下面是該命令的語法
[address1[,address2]]c\
Replace text
好比,替換文本中的第三行爲新的內容
$ sed '3 c 3) Adultry, Paulo Coelho, 324' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) Adultry, Paulo Coelho, 324
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
SED也接受模式做爲地址
$ sed '/The Alchemist/ c 3) Adultry, Paulo Coelho, 324' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) Adultry, Paulo Coelho, 324
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
多行替換也是支持的,下面的命令實現了將第4-6行內容替換爲單行
$ sed '4, 6 c 4) Adultry, Paulo Coelho, 324' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) Adultry, Paulo Coelho, 324
插入命令 i
插入命令與追加命令相似,惟一的區別是插入命令是在匹配的位置前插入新的一行。
[address]i\
Insert text
下面的命令會在第四行前插入新的一行
$ sed '4 i 7) Adultry, Paulo Coelho, 324' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
7) Adultry, Paulo Coelho, 324
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
轉換命令 y
轉換(Translate)命令 y 是惟一能夠處理單個字符的sed編輯器命令。轉換命令格式 以下
[address]y/inchars/outchars/
轉換命令會對inchars和outchars值進行一對一的映射。inchars中的第一個字符會被轉換爲outchars中的第一個字符,第二個字符會被轉換成outchars中的第二個字符。這個映射過程會一直持續處處理完指定字符。若是inchars和outchars的長度不一樣,則sed編輯器會產生一 條錯誤消息。
$ echo "1 5 15 20" | sed 'y/151520/IVXVXX/'
I V IV XX
輸出隱藏字符命令 l
你能經過直接觀察區分出單詞是經過空格仍是tab進行分隔的嗎?顯然是不能的,可是SED能夠爲你作到這點。使用l
命令(英文字母L的小寫)能夠顯示文本中的隱藏字符(例如t
或者$
字符)。
[address1[,address2]]l
[address1[,address2]]l [len]
爲了測試該命令,咱們首先將books.txt中的空格替換爲tab。
$ sed 's/ /\t/g' books.txt > junk.txt
接下來執行l
命令
$ sed -n 'l' junk.txt
1)\tStorm\tof\tSwords,\tGeorge\tR.\tR.\tMartin,\t1216\t$
2)\tThe\tTwo\tTowers,\tJ.\tR.\tR.\tTolkien,\t352\t$
3)\tThe\tAlchemist,\tPaulo\tCoelho,\t197\t$
4)\tThe\tFellowship\tof\tthe\tRing,\tJ.\tR.\tR.\tTolkien,\t432\t$
5)\tThe\tPilgrimage,\tPaulo\tCoelho,\t288\t$
6)\tA\tGame\tof\tThrones,\tGeorge\tR.\tR.\tMartin,\t864$
使用l
命令的時候,一個頗有趣的特性是咱們可使用它來實現文本按照指定的寬度換行。
$ sed -n 'l 25' books.txt
1) Storm of Swords, Geor\
ge R. R. Martin, 1216 $
2) The Two Towers, J. R.\
R. Tolkien, 352 $
3) The Alchemist, Paulo \
Coelho, 197 $
4) The Fellowship of the\
Ring, J. R. R. Tolkien,\
432 $
5) The Pilgrimage, Paulo\
Coelho, 288 $
6) A Game of Thrones, Ge\
orge R. R. Martin, 864$
上面的示例中在l
命令後跟了一個數字25,它告訴SED按照每行25個字符進行換行,若是指定這個數字爲0的話,則只有在存在換行符的狀況下才進行換行。
l
命令是GNU-SED的一部分,其它的一些變體中可能沒法使用該命令。
退出命令 q
在SED中,可使用Quit
命令退出當前的執行流
[address]q [address]q [value]
須要注意的是,q
命令不支持地址範圍,只支持單個地址匹配。默認狀況下SED會按照讀取、執行、重複的工做流執行,但當它遇到q
命令的時候,它會退出當前的執行流。
$ sed '3 q' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
$ sed '/The Alchemist/ q' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
q
命令也支持提供一個value,這個value將做爲程序的返回代碼返回
$ sed '/The Alchemist/ q 100' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
$ echo $?
100
文件讀取命令 r
在SED中,咱們可讓SED使用Read命令從外部文件中讀取內容而且在知足條件的時候顯示出來。
[address]r file
須要注意的是,r
命令和文件名之間必須只有一個空格。
下面的示例會打開junk.txt文件,將其內容插入到books.txt文件的第三行以後
$ echo "This is junk text." > junk.txt
$ sed '3 r junk.txt' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
This is junk text.
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
r
命令也支持地址範圍,例如3, 5 r junk.txt會在第三行,第四行,第五行後面分別插入junk.txt的內容
執行外部命令 e
若是你看過三十分鐘學會AWK一文,你可能已經知道了在AWK中能夠執行外部的命令,那麼在SED中咱們是否也能夠這樣作?
答案是確定的,在SED中,咱們可使用e
命令執行外部命令
[address1[,address2]]e [command]
下面的命令會在第三行以前執行date命令
$ sed '3 e date' books.txt
1) Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
2016年11月29日 星期二 22時46分14秒 CST
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
另外一個示例
$ sed '3,5 e who' books.txt
1) Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
mylxsw console Nov 29 19:30
mylxsw ttys000 Nov 29 22:45
3) The Alchemist, Paulo Coelho, 197
mylxsw console Nov 29 19:30
mylxsw ttys000 Nov 29 22:45
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
mylxsw console Nov 29 19:30
mylxsw ttys000 Nov 29 22:45
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
若是你仔細觀察e
命令的語法,你會發現其實它的command參數是可選的。在沒有提供外部命令的時候,SED會將模式空間中的內容做爲要執行的命令。
$ echo -e "date\ncal\nuname" > commands.txt
$ cat commands.txt
date
cal
uname
$ sed 'e' commands.txt
2016年11月29日 星期二 22時50分30秒 CST
十一月 2016
日 一 二 三 四 五 六
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Darwin
排除命令 !
感嘆號命令(!)用來排除命令,也就是讓本來會起做用的命令不起做用。
$ sed -n '/Paulo/p' books.txt
3) The Alchemist, Paulo Coelho, 197
5) The Pilgrimage, Paulo Coelho, 288
$ sed -n '/Paulo/!p' books.txt
1) Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
6) A Game of Thrones, George R. R. Martin, 864
如上例所示,p
命令原先是隻輸出匹配Paulo的行,添加!
以後,變成了只輸出不匹配Paulo的行。
$ sed -n '1!G; h; $p' books.txt
6) A Game of Thrones, George R. R. Martin, 864
5) The Pilgrimage, Paulo Coelho, 288
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
3) The Alchemist, Paulo Coelho, 197
2) The Two Towers, J. R. R. Tolkien, 352
1) Storm of Swords, George R. R. Martin, 1216
上面的命令實現了相似tac
命令相似的輸出,將文本內容倒序輸出。看起來有些晦澀難懂,分解一下卻十分簡單:
1!G 這句的意思是出了第一行以外,處理每一行的時候都將保持空間中的內容追加到模式空間(正序->倒序)
h 將模式空間中的內容複製到保持空間以備下一行匹配的時候追加到下一行的後面
$p 若是匹配到最後一行的話則輸出模式空間中的內容
上述步驟不斷重複直到文本結束恰好將文件內容翻轉了一次
多行命令
在使用sed編輯器的基礎命令時,你可能注意到了一個侷限。全部的sed編輯器命令都是針對單行數據執行操做的。在sed編輯器讀取數據流時,它會基於換行符的位置將數據分紅行。sed編輯器根據定義好的腳本命令一次處理一行數據,而後移到下一行重複這個過程。
幸運的是,sed編輯器的設計人員已經考慮到了這種狀況,並設計了對應的解決方案。sed編輯器包含了三個可用來處理多行文本的特殊命令。
N:將數據流中的下一行加進來建立一個多行組來處理
D:刪除多行組中的一行
P:打印多行組中的一行
N - 加載下一行
默認狀況下,SED是基於單行進行操做的,有些狀況下咱們可能須要使用多行進行編輯,啓用多行編輯使用N
命令,與n
不一樣的是,N
並不會清除、輸出模式空間的內容,而是採用了追加模式。
[address1[,address2]]N
下面的示例將會把books2.txt中的標題和做者放到同一行展現,而且使用逗號進行分隔
$ sed 'N; s/\n/,/g' books2.txt
A Storm of Swords ,George R. R. Martin
The Two Towers ,J. R. R. Tolkien
The Alchemist ,Paulo Coelho
The Fellowship of the Ring ,J. R. R. Tolkien
The Pilgrimage ,Paulo Coelho
A Game of Thrones ,George R. R. Martin
D - 刪除多行中的一行
sed編輯器提供了多行刪除命令D,它只刪除模式空間中的第一行。該命令會刪除到換行符(含 換行符)爲止的全部字符。
$ echo '\nThis is the header line.\nThis is a data line.\n\nThis is the last line.' | sed '/^$/{N; /header/D}'
This is the header line.
This is a data line.
This is the last line.
P - 輸出多行中的一行
P
命令用於輸出N
命令建立的多行文本的模式空間中的第一行。
[address1[,address2]]P
例以下面的命令只輸出了圖書的標題
$ sed -n 'N;P' books2.txt
A Storm of Swords
The Two Towers
The Alchemist
The Fellowship of the Ring
The Pilgrimage
A Game of Thrones
其它命令
n - 單行next
小寫的n命令會告訴sed編輯器移動到數據流中的下一文本行,而且覆蓋當前模式空間中的行。
$ cat data1.txt
This is the header line.
This is a data line.
This is the last line.
$ sed '/header/{n ; d}' data1.txt
This is the header line.
This is a data line.
This is the last line.
上面的命令中,首先會匹配包含header的行,以後將移動到數據流的下一行,這裏是一個空行,而後執行d
命令對改行進行刪除,全部就看到了這樣的結果:第一個空行被刪除掉了。
v - SED版本檢查
v
命令用於檢查SED的版本,若是版本大於參數中的版本則正常執行,不然失敗
[address1[,address2]]v [version]
例如
$ sed --version
sed (GNU sed) 4.2.2
$ sed 'v 4.2.3' books.txt
sed: -e expression #1, char 7: expected newer version of sed
$ sed 'v 4.2.2' books.txt
1) Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
特殊字符
在SED中提供了兩個能夠用做命令的特殊字符:= 和 & 。
=
命令
=
命令用於輸出行號,語法格式爲
[/pattern/]=
[address1[,address2]]=
例如爲每一行輸出行號
$ sed '=' books2.txt
1
A Storm of Swords
2
George R. R. Martin
...
只爲1-4行輸出行號
$ sed '1, 4=' books2.txt
1
A Storm of Swords
2
George R. R. Martin
3
The Two Towers
4
J. R. R. Tolkien
The Alchemist
Paulo Coelho
The Fellowship of the Ring
J. R. R. Tolkien
The Pilgrimage
Paulo Coelho
A Game of Thrones
George R. R. Martin
匹配Paulo的行輸出行號
$ sed '/Paulo/ =' books2.txt
A Storm of Swords
George R. R. Martin
The Two Towers
J. R. R. Tolkien
The Alchemist
6
Paulo Coelho
The Fellowship of the Ring
J. R. R. Tolkien
The Pilgrimage
10
Paulo Coelho
A Game of Thrones
George R. R. Martin
最後一行輸出行號,這個命令比較有意思了,能夠用於輸出文件總共有多少行
$ sed -n '$ =' books2.txt
12
&
命令
特殊字符&
用於存儲匹配模式的內容,一般與替換命令s
一塊兒使用。
$ sed 's/[[:digit:]]/Book number &/' books.txt
Book number 1) Storm of Swords, George R. R. Martin, 1216
Book number 2) The Two Towers, J. R. R. Tolkien, 352
Book number 3) The Alchemist, Paulo Coelho, 197
Book number 4) The Fellowship of the Ring, J. R. R. Tolkien, 432
Book number 5) The Pilgrimage, Paulo Coelho, 288
Book number 6) A Game of Thrones, George R. R. Martin, 864
上述命令用於匹配每一行第一個數字,在其前面添加 Book number 。而下面這個命令則匹配最後一個數字,並修改成Pages =
。其中[[:digit:]]* *$
可能比較費解,這一部分實際上是:匹配0個或多個數字+0個或多個空格+行尾。
sed 's/[[:digit:]]* *$/Pages = &/' books.txt
1) Storm of Swords, George R. R. Martin, Pages = 1216
2) The Two Towers, J. R. R. Tolkien, Pages = 352
3) The Alchemist, Paulo Coelho, Pages = 197
4) The Fellowship of the Ring, J. R. R. Tolkien, Pages = 432
5) The Pilgrimage, Paulo Coelho, Pages = 288
6) A Game of Thrones, George R. R. Martin, Pages = 864
字符串
替換命令 s
文本替換命令很是常見,其格式以下
[address1[,address2]]s/pattern/replacement/[flags]
在前面咱們使用的books.txt文件中,咱們使用逗號「,」分隔每一列,下面的示例中,咱們會使用替換命令將其替換爲管道符「|」:
$ sed 's/,/ |/' books.txt
1) Storm of Swords | George R. R. Martin, 1216 2) The Two Towers | J. R. R. Tolkien, 352
3) The Alchemist | Paulo Coelho, 197 4) The Fellowship of the Ring | J. R. R. Tolkien, 432
5) The Pilgrimage | Paulo Coelho, 288 6) A Game of Thrones | George R. R. Martin, 864
是否是以爲哪裏不對?相信你已經發現,每一行的第二個逗號都沒有被替換,只有第一個被替換了,確實如此,在SED中,使用替換命令的時候默認只會對第一個匹配的位置進行替換。使用g
選項告訴SED對全部內容進行替換:
$ sed 's/,/ | /g' books.txt
1) Storm of Swords | George R. R. Martin | 1216
2) The Two Towers | J. R. R. Tolkien | 352
3) The Alchemist | Paulo Coelho | 197
4) The Fellowship of the Ring | J. R. R. Tolkien | 432
5) The Pilgrimage | Paulo Coelho | 288
6) A Game of Thrones | George R. R. Martin | 864
若是對匹配模式(或地址範圍)的行進行替換,則只須要在
s
命令前添加地址便可。好比只替換匹配The Pilgrimage的行:sed '/The Pilgrimage/ s/,/ | /g' books.txt
還有一些其它的選項,這裏就簡單的描述一下,不在展開講解
數字n: 只替換第n次匹配,好比
sed 's/,/ | /2' books.txt
,只替換每行中第二個逗號p:只輸出改變的行,好比
sed -n 's/Paulo Coelho/PAULO COELHO/p' books.txt
w:存儲改變的行到文件,好比
sed -n 's/Paulo Coelho/PAULO COELHO/w junk.txt' books.txt
i:匹配時忽略大小寫,好比
sed -n 's/pAuLo CoElHo/PAULO COELHO/pi' books.txt
在執行替換操做的時候,若是要替換的內容中包含/
,這個時候怎麼辦?很簡單,添加轉義操做符。
$ echo "/bin/sed" | sed 's/\/bin\/sed/\/home\/mylxsw\/src\/sed\/sed-4.2.2\/sed/'
/home/mylxsw/src/sed/sed-4.2.2/sed
上面的命令中,咱們使用`對
/進行了轉義,不過表達式已經看起來很是難看了,在SED中還可使用
|,
@,
^,
!`做爲命令的分隔符,因此,下面的幾個命令和上面的是等價的
echo "/bin/sed" | sed 's|/bin/sed|/mylxsw/mylxsw/src/sed/sed-4.2.2/sed|' echo "/bin/sed" | sed 's@/bin/sed@/home/mylxsw/src/sed/sed-4.2.2/sed@' echo "/bin/sed" | sed 's^/bin/sed^/home/mylxsw/src/sed/sed-4.2.2/sed^' echo "/bin/sed" | sed 's!/bin/sed!/home/mylxsw/src/sed/sed-4.2.2/sed!'
匹配子字符串
前面咱們學習了替換命令的用法,如今讓咱們看看如何獲取匹配文本中的某個子串。
在SED中,使用(
和)
對匹配的內容進行分組,使用N
的方式進行引用。請看下面示例
$ echo "Three One Two" | sed 's|\(\w\+\) \(\w\+\) \(\w\+\)|\2 \3 \1|'
One Two Three
咱們輸出了Three,One,Two三個單詞,在SED的替換規則中,使用空格分隔了三小段正則表達式(w+)
來匹配每個單詞,後面使用1
,,2
,3
分別引用它們的值。
管理模式
前面已經講解過模式空間和保持空間的用法,在本節中咱們將會繼續探索它們的用法。
本部份內容暫未更新,請關注程序猿成長計劃 項目,我將最早在Github的這個倉庫中更新最新內容。
正則表達式
這一部分就是標準正則表達式的一些特殊字符以元字符,比較熟悉的請略過。
標準正則表達式
^
匹配行的開始。
$ sed -n '/^The/ p' books2.txt
The Two Towers, J. R. R. Tolkien
The Alchemist, Paulo Coelho
The Fellowship of the Ring, J. R. R. Tolkien
The Pilgrimage, Paulo Coelho
$
匹配行的結尾
$ sed -n '/Coelho$/ p' books2.txt
The Alchemist, Paulo Coelho
The Pilgrimage, Paulo Coelho
.
匹配單個字符(除行尾)
$ echo -e "cat\nbat\nrat\nmat\nbatting\nrats\nmats" | sed -n '/^..t$/p'
cat
bat
rat
mat
[]
匹配字符集
$ echo -e "Call\nTall\nBall" | sed -n '/[CT]all/ p'
Call
Tall
[^]
排除字符集
$ echo -e "Call\nTall\nBall" | sed -n '/[^CT]all/ p'
Ball
[-]
字符範圍。
$ echo -e "Call\nTall\nBall" | sed -n '/[C-Z]all/ p'
Call
Tall
? ,\+ ,*
分別對應0次到1次,一次到屢次,0次到屢次匹配。
{n} ,{n,} ,{m, n}
精確匹配N次,至少匹配N次,匹配M-N次
|
或操做。
$ echo -e "str1\nstr2\nstr3\nstr4" | sed -n '/str\(1\|3\)/ p'
str1
str3
POSIX兼容的正則
主要包含[:alnum:]
,[:alpha:]
,[:blank:]
,[:digit:]
,[:lower:]
,[:upper:]
,[:punct:]
,[:space:]
,這些基本都見名之意,不在贅述。
元字符
s
匹配單個空白內容
$ echo -e "Line\t1\nLine2" | sed -n '/Line\s/ p'
Line 1
S
匹配單個非空白內容。
w , W
單個單詞、非單詞。
經常使用代碼段
Cat命令
模擬cat
命令比較簡單,有下面兩種方式
$ sed '' books.txt
1) Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
$ sed -n 'p' books.txt
1) Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
移除空行
$ echo -e "Line #1\n\n\nLine #2" | sed '/^$/d'
Line #1
Line #2
刪除連續空行
$ echo -e "Line #1\n\n\nLine #2" | sed '/./,/^$/!d'
Line #1
Line #2
刪除開頭的空行
$ echo -e "\nLine #1\n\nLine #2" | sed '/./,$!d'
Line #1
Line #2
刪除結尾的空行
$ echo -e "\nLine #1\nLine #2\n\n" | sed ':start /^\n*$/{$d; N; b start }'
Line #1
Line #2
過濾全部的html標籤
$ cat html.txt
<html>
<head>
<title>This is the page title</title>
</head>
<body>
<p> This is the <b>first</b> line in the Web page.
This should provide some <i>useful</i> information to use in our sed script.
</body>
</html>
$ sed 's/<[^>]*>//g ; /^$/d' html.txt
This is the page title
This is the first line in the Web page.
This should provide some useful information to use in our sed script.
從C++程序中移除註釋
有下面這樣一個cpp文件
$ cat hello.cpp
#include <iostream>
using namespace std;
int main(void) {
// Displays message on stdout.
cout >> "Hello, World !!!" >> endl;
return 0; // Return success.
}
執行下面的命令能夠移除註釋
$ sed 's|//.*||g' hello.cpp
#include <iostream>
using namespace std;
int main(void)
{
cout >> "Hello, World !!!" >> endl;
return 0;
}
爲某些行添加註釋
$ sed '3,5 s/^/#/' hello.sh
#!/bin/bash
#pwd
#hostname
#uname -a
who
who -r
lsb_release -a
實現Wc -l命令
wc -l
命令用於統計文件中的行數,使用SED也能夠模擬該命令
$ wc -l hello.cpp
9 hello.cpp
$ sed -n '$ =' hello.cpp
9
模擬實現head
命令
head
命令用於輸出文件中的前10行內容。
$ head books2.txt
A Storm of Swords
George R. R. Martin
The Two Towers
J. R. R. Tolkien
The Alchemist
Paulo Coelho
The Fellowship of the Ring
J. R. R. Tolkien
The Pilgrimage
Paulo Coelho
使用SED中的sed '10 q'
能夠模擬它的實現
$ sed '10 q' books.txt
A Storm of Swords
George R. R. Martin
The Two Towers
J. R. R. Tolkien
The Alchemist
Paulo Coelho
The Fellowship of the Ring
J. R. R. Tolkien
The Pilgrimage
Paulo Coelho
模擬tail -1
命令
tail -1
輸出文件的最後一行。
$ cat test.txt
Line #1
Line #2
$ tail -1 test.txt
Line #2
$ sed $ sed -n '$p' test.txt
Line #2
模擬Dos2unix
命令
在DOS環境中,換行符是使用CR/LF兩個字符一塊兒表示的,下面命令模擬了dos2unix
命令轉換這些換行符爲UNIX換行符。
在GNU/Linux環境中,CR/LF一般使用"^M"(不是簡單的兩個符號組合,請使用快捷鍵Ctrl+v,Ctrl+m輸入)進行表示。
$ echo -e "Line #1\r\nLine #2\r" > test.txt
$ file test.txt
test.txt: ASCII text, with CRLF line terminators
$ sed 's/^M$//' test.txt > new.txt
$ file new.txt
new.txt: ASCII text
$ cat -vte new.txt
Line #1$
Line #2$
模擬Unix2dos
命令
$ file new.txt
new.txt: ASCII text
$ sed 's/$/\r/' new.txt > new2.txt
$ file new2.txt
new2.txt: ASCII text, with CRLF line terminators
$ cat -vte new2.txt
Line #1^M$
Line #2^M$
模擬cat -E
命令
cat -E
命令會在每一行的行尾輸出一個$符號。
$ echo -e "Line #1\nLine #2" | cat -E
Line #1$
Line #2$
$ echo -e "Line #1\nLine #2" | sed 's|$|&$|'
Line #1$
Line #2$
注意,在Mac下不支持
cat -E
,能夠直接使用sed代替
模擬cat -ET
命令
cat -ET
命令不只對每一行的行尾添加$,還會將每一行中的TAB顯示爲^I。
$ echo -e "Line #1\tLine #2" | cat -ET
Line #1^ILine #2$
$ echo -e "Line #1\tLine #2" | sed -n 'l' | sed 'y/\\t/^I/'
Line #1^ILine #2$
模擬nl
命令
命令nl
能夠爲輸入內容的每一行添加行號,記得以前介紹的=
操做符吧,在SED中咱們能夠用它來實現與nl
命令相似的功能。
$ echo -e "Line #1\nLine #2" |nl
1 Line #1
2 Line #2
$ echo -e "Line #1\nLine #2" | sed = | sed 'N;s/\n/\t/'
1 Line #1
2 Line #2
上面的SED命令使用了兩次,第一次使用=
操做符爲每一行輸出行號,注意這個行號是獨佔一行的,所以使用管道符鏈接了第二個SED命令,每次讀取兩行,將換行符替換爲Tab,這樣就模擬出了nl
命令的效果。
模擬cp
命令
$ sed -n 'w dup.txt' data.txt
$ diff data.txt dup.txt
$ echo $?
0
模擬expand
命令
expand
命令會轉換輸入中的TAB爲空格,在SED中也能夠模擬它
$ echo -e "One\tTwo\tThree" > test.txt
$ expand test.txt > expand.txt
$ sed 's/\t/ /g' test.txt > new.txt
$ diff new.txt expand.txt
$ echo $?
0
模擬tee
命令
tee
命令會將數據輸出到標準輸出的同時寫入文件。
$ echo -e "Line #1\nLine #2" | tee test.txt
Line #1
Line #2
在SED中,實現該命令很是簡單
$ sed -n 'p; w new.txt' test.txt
One Two Three
模擬cat -s
命令
cat -s
命令會將輸入文件中的多行空格合併爲一行。
$ echo -e "Line #1\n\n\n\nLine #2\n\n\nLine #3" | cat -s
Line #1
Line #2
Line #3
在SED中實現
$ echo -e "Line #1\n\n\n\nLine #2\n\n\nLine #3" | sed '1s/^$//p;/./,/^$/!d'
Line #1
Line #2
Line #3
這裏須要注意的是/./,/^$/!d
這個命令,它的意思是匹配區間/./
到/^$
,區間的開始會匹配至少包含一個字符的行,結束會匹配一個空行,在這個區間中的行不會被刪除。
模擬grep
命令
$ echo -e "Line #1\nLine #2\nLine #3" | grep 'Line #1'
Line #1
$ echo -e "Line #1\nLine #2\nLine #3" | sed -n '/Line #1/p'
Line #1
模擬grep -v
命令
$ echo -e "Line #1\nLine #2\nLine #3" | grep -v 'Line #1'
Line #2
Line #3
$ echo -e "Line #1\nLine #2\nLine #3" | sed -n '/Line #1/!p'
Line #2
Line #3
模擬tr
命令
tr
命令用於字符轉換
$ echo "ABC" | tr "ABC" "abc"
abc
$ echo "ABC" | sed 'y/ABC/abc/'
abc
寫在最後
看到這裏,你確定要吐槽了,不是說了三十分鐘學會嗎?你肯定你能三十分鐘學會?上次的三十分鐘學會AWK說三十分鐘學會不靠譜,此次又不靠譜了。很差意思,這裏的三十分鐘其實只是爲了吸引你的注意而已,只有在你已經用過SED並對它的一些特性有所瞭解的狀況下三十分鐘看完纔是有可能的,畢竟那麼多特殊字符,那麼多命令須要記住。不過話說回來,看完以後你有收穫嗎?有的話,那本文的目的就達到了,以後用到SED的時候再回來參考一下就能夠了。
本文將會持續修正和更新,最新內容請參考個人 GITHUB 上的 程序猿成長計劃 項目,歡迎 Star。