Sed基本命令


本教學將介紹一些有用的sed命令和使用範例。考慮一下我們有一個文字檔案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

刪除 d 命令

sed刪除命令用 d 字元表示,並將其用於刪除從一個給定的模式緩衝器的一行或多行。以下是 sed 刪除命令的基本語法:

[address1[,address2]]d

這裡address1和address2分別為起始和結束地址,其可以是行號或模式串。這兩個地址是可選引數,如果不提供它們作為字首-d命令,那麼它會刪除,如下圖所示所有行:

[jerry]$ sed 'd' books.txt 

上面的命令將刪除所有傳遞給 sed 的行並且沒有行資料會列印在螢幕上。

下面指示 sed 只在某些行上使用。下面的例子中只刪除4行。

[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也接受用逗號分隔地址範圍(,)。可以指示sed 刪除N1到N2行。例如,下面的例子將刪除從2到4的所有行。

[jerry]$ sed '2,4d' 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

也可以指定模式作為地址。下面的範例刪除作者是 Paulo Coelho的所有書籍。

[jerry]$ 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之間的所有行。

[jerry]$ sed '/Storm/,/Fellowship/d' books.txt  
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864 
可以使用美元符號($),加號(+),和波浪符號(?)運算子使用sed -d命令刪除。

寫入w 命令

sed的寫命令是由 w 字元表示,並且它用於儲存模式緩衝區的一個檔案中內容。以下是sed 寫命令的基本語法:

[address1[,address2]]w 

這裡,address1 和 address2 分別是模式緩衝儲存器的起始和結束地址,該地址可以是行號或模式串。這兩個地址是可選引數,如果不提供它們的字首給w命令,那麼它將儲存完整的模式緩衝區到給定的檔案,如下所示:

[jerry]$ sed -n 'w books.bak' books.txt 

上面的命令將建立另一個名為books.bak的檔案。這是books.txt檔案複製檔案。

sed允許建立包含原始檔只有某些行的檔案。以下命令是副本只從books.txt偶數行資料到books.bak檔案。

[jerry]$ sed -n '2~2w books.bak' books.txt  

如果將檢查books.bak檔案的內容,那麼它將有以下幾行:

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 

也可以指定模式作為地址。下面的例子中儲存作者為 Paulo Coelho 的所有書籍。

[jerry]$ sed -n -e '/Paulo Coelho/w books.bak' books.txt

如果將檢查books.bak檔案的內容,那麼它將有以下幾行:

3) The Alchemist, Paulo Coelho, 197
5) The Pilgrimage, Paulo Coelho, 288

追加 a 命令

任何一個文字編輯器的最有用的操作是提供附/追加功能。sed通過其由一個字元表示追加命令支援該操作。以下是sed追加命令的基本語法:

[address]a  'text to be appended'

這裡的地址是模式緩衝區地址,可以是行號或模式字串來表示,其中的文字將被追加的位置。以下是追加後的行數4新書項命令。

[jerry]$ sed '4a 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

可以使用$符號插入的檔案結束後面的行,如下所示:

[jerry]$ 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.

[jerry]$ 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字元來表示命令。此命令可以幫助更換新文字的現有行。以下是 sed 改變命令的基本語法:

[address1[,address2]]c 'Next text'

這裡,address1 和 address2 分別是模式緩衝區的起始和結束地址,該地址可以是行號或模式串。這兩個地址是可選引數,如果不提供字首,則該命令將替換為新文字的每一行,如下所示:

[jerry]$ sed 'c This is new text' books.txt 

執行上面的程式碼,會得到如下結果:

This is new text
This is new text
This is new text
This is new text
This is new text
This is new text

下面是範例替換一些其他文字的第三行。

[jerry]$ 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

還可以指定要匹配並採用c運算子的幫助下替換模式如下:

[jerry]$ 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 

sed 還允許替換多行以及一行。下面的範例是從第4行到第6行,將它們替換為新的文字。

[jerry]$ sed '4, 6c 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 命令

插入命令工作起來作為追加的方式相同。唯一的區別在於,它插入一個特定位置之前的行。以下是sed的插入命令的基本語法:

[address]i 'Text to be inserted' 

這裡地址是模式緩衝區地址,可以用行號或模式串來表示,其中的文字將被插入的位置。下面是插入第4行之前的一本新書項命令。

[jerry]$ 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

在一個檔案的開頭插入文字,提供的行地址為1.下列命令說明這一點:

[jerry]$ sed '1 i 7) Adultry, Paulo Coelho, 324' books.txt

執行上面的程式碼,會得到如下結果:

7) Adultry, Paulo Coelho, 324
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

下面的命令插入的最後一行前行。

[jerry]$ sed '$ 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
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
7) Adultry, Paulo Coelho, 324
6) A Game of Thrones, George R. R. Martin, 864

轉換 y 命令

sed提供一個命令轉換到字元,它表示為y。它通過位置轉換字元。以下是sed轉換命令基本語法:

[address1[,address2]]y/list-1/list-2/

注意,轉換是基於字元的,從列表1到可用的字元在表2中的位置是相同的位置和兩個列表必須是明確的字元列表。正規表示式和字元集是不支援的。此外,表1和表2的尺寸必須相同。

下面的範例將大寫字母為小寫字母:

[jerry]$ echo "BCDAFE" | sed 'y/ABCDEF/abcdef/' 

執行上面的程式碼,會得到如下結果:

bcdafe

Sed l 命令

sed使用 -l 命令可以在文字顯示隱藏字元。例如,\t製表符和$符結束行。下面給出的是sed的 i 命令的語法。

[address1[,address2]]l 

or

[address1[,address2]]l [len] 

現在,在 books.txt 輸入一個標籤空間,並嘗試使用 l 命令顯示的內容:

[jerry]$ sed -n 'l' books.txt

執行上面的程式碼,會得到如下結果:

1)\tA 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的一定字元數之後進行換行。下面的例子25個字元後換行。

[jerry]$ sed -n 'l 25' books.txt

執行上面的程式碼,會得到如下結果:

1) A Storm of Swords,Geo\ 
rge R. R. Martin,1216$ 
2) The Two Towers,J. R. \ 
R. Tolkien,352$ 
3) The Alchemist,Paulo C\ 
oelho,197$ 
4) The Fellowship of the\ 
 Ring,J. R. R. Tolkien,4\ 
32$ 
5) The Pilgrimage,Paulo \ 
Coelho,288$ 
6) A Game of Thrones,Geo\ 
rge R. R. Martin ,864$

纏繞限0意味著永遠斷行,除非有一個新行字元。下面簡單的命令說明了這一點。

[jerry]$ sed -n 'l 0' 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$ 

退出 q 命令

退出命令表示 sed 退出當前執行流程,它是由q命令表示。以下是 sed 的基本語法退出命令:

[address]q 
[address]q [value]

需要注意的是退出命令不接受地址範圍,它僅支援一個地址。預設情況下,Sed如下讀取,執行和重複的工作流程;但退出命令時只是停止當前執行並退出來。

以下是命令從該檔案的第3行列印。

[jerry]$ 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

還可以使用文字模式,而不是行號。當一個給定的模式匹配成功如下命令退出。

[jerry]$ 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

除了這一點,sed還可以接受,可用於作為退出狀態值。以下命令顯示了它的退出狀態為100。

[jerry]$ 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

現在讓我們驗證的退出狀態。

[jerry]$ echo $? 

在執行上面的程式碼,會得到如下結果:

100

讀取 r 命令

可以讓Sed讀取檔案的內容,並顯示在一個特定的條件相匹配。讀指令由r操作者來表示。以下是Sed的基本語法讀取命令:

[address]r file

讓我們用一個簡單的例子了解它。建立一個名為junk.txt範例檔案。

[jerry]$ echo "This is junk text." > junk.txt 

下面的命令指示Sed來讀取 junk.txt 的內容,在第三行之後插入。

[jerry]$ 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

下面的命令在第三,第四和第五行之後插入 junk.txt 內容。

[jerry]$ sed '3, 5r 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 
This is junk text. 
5) The Pilgrimage, Paulo Coelho, 288 
This is junk text. 
6) A Game of Thrones, George R. R. Martin, 864

類似其他的sed命令,讀取命令也接受模式作為地址。例如,下面的命令插入junk.txt 檔案內容時,所述模式匹配成功。

[jerry]$ sed '/Paulo/ 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 
This is junk text. 
6) A Game of Thrones, George R. R. Martin, 864 

執行 e 命令

我們可以從Sed使用執行命令,執行外部命令,它是通過電子郵件操作符表示。以下是Sed執行命令的基本語法:

[address1[,address2]]e [command]

這裡,address1 和 address2是模式緩衝儲存器的地址,該地址可以為行號或模式字串,及命令將執行一個給定的地址。

例如,下面的 sed 命令是當遇到從給定的檔案中的第三行之前執行 UNIX 日期命令。

[jerry]$ sed '3 e date' books.txt

當執行上面的程式碼,會得到如下結果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
Sun Sep  7 18:04:49 IST 2014 
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

類似其他的命令,它也可以接受模式作為地址。例如,下面範例執行date命令,當一個模式匹配成功。注意,每一個模式匹配後,首先執行該命令,然後將模式緩衝區的內容顯示。

[jerry]$ sed '/Paulo/ e date' books.txt 

當執行上面的程式碼,會得到如下結果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
Sun Sep  7 18:06:04 IST 2014 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
Sun Sep  7 18:06:04 IST 2014 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

當 e 之後沒有命令提供,它將該模式緩衝區的內容作為一個外部命令。為了說明這一點,建立一些簡單的命令在 commands.txt 的檔案中。

[jerry]$ echo -e "date\ncal\nuname" > commands.txt 
[jerry]$ cat commands.txt

當執行上面的程式碼,會得到如下結果:

date 
cal 
uname

從檔案的命令不言自明。下面簡單的例子,提供了一個使用 sed 指令碼的命令:

[jerry]$ sed 'e' commands.txt 

當執行上面的程式碼,會得到如下結果:

Sun Sep  7 18:14:20 IST 2014 
   September 2014      
Su Mo Tu We Th Fr Sa   
    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               
                       
Linux 

正如其他sed命令,在執行命令也接受地址的所有的有效範圍。

雜項命令

預設情況下,sed操作在一行上,但是它也可以在多行上操作。多行命令由大寫字母表示。例如,多行命令不同的是,N個命令不清除並列印模式空間。相反,它增加了一個新行(\n),在當前的模式空間的末端,並從輸入檔案中的下一行追加到當前模式空間,並與Sed的標準流量通過執行Sed命令的其餘部分將繼續。下面給出的是N命令的語法。

[address1[,address2]]N

稍微修改 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
A Game of Thrones
George R. R. Martin

讓我們列印一個逗號分隔的書名和各自的作者名單。下面的例子說明了這一點。

[jerry]$ sed 'N; s/\n/,/g' 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 
A Game of Thrones, George R. R. Martin

了解上面的例子如何工作。 n命令讀取第一行,即Storm 模式緩衝區,並追加\n接著的下一行。模式空間現在包含Swords\nGeorge R. R. Martin。在接下來的步驟中,我們用逗號替換換行符。

就像 p 這樣的命令,我們有一個 P 命令列印的第一部分(最多嵌入的換行符)由 N 命令建立的多行模式空間。下面給出的是 P 命令的語法,它類似於p命令。

[address1[,address2]]P 

在前面的例子中,我們看到了N命令建立的書名和作者的新一行 - 分隔的列表。列印它僅第一部分,即,這本書的標題。下面的命令說明了這一點。

[jerry]$ sed -n 'N;P' books.txt

當執行上面的程式碼,會得到如下結果:

A Storm of Swords 
The Two Towers 
The Alchemist 
The Fellowship of the Ring 
The Pilgrimage 
A Game of Thrones

請注意,在不存在 N,它的行為相同於 p 命令。下面簡單的命令說明了這種情況。

[jerry]$ sed -n 'P' 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 
A Game of Thrones 
George R. R. Martin

除了這一點,Sed還提供了用於檢查版本的一個 v 命令。如果所提供的版本大於所述安裝 sed 的版本,然後命令執行失敗。請注意,此選項是GNU具體,可能無法與Sed的其他版本的工作。下面給出的是 v 命令的語法。

[address1[,address2]]v [version]

首先,找出Sed的當前版本。

[jerry]$ sed --version 

當執行上面的程式碼,會得到如下結果:

sed (GNU sed) 4.2.2 

在下面的例子中,Sed版本高於4.2.2版本,因此sed命令中止執行。

[jerry]$ sed 'v 4.2.3' books.txt 

當執行上面的程式碼,會得到如下結果:

sed: -e expression #1, char 7: expected newer version of sed

但是,如果所提供的版本是小於或等於4.2.2版本,則命令會按預期工作。

[jerry]$ sed 'v 4.2.2' 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 
A Game of Thrones George R. R. Martin