sed
意為流編輯器(Stream Editor),在Shell腳本和Makefile中作為過濾器使用非常普遍,也就是把前一個程序的輸出引入sed的輸入,經過一系列編輯命令轉換為另一種格式輸出。sed
和vi
都源於早期UNIX的ed
工具,所以很多sed
命令和vi
的末行命令是相同的。
sed
命令行的基本格式為
sed option 'script' file1 file2 ... sed option -f scriptfile file1 file2 ...
sed
處理的檔案既可以由標準輸入重定向得到,也可以當命令行參數傳入,命令行參數可以一次傳入多個檔案,sed
會依次處理。sed
的編輯命令可以直接當命令行參數傳入,也可以寫成一個腳本檔案然後用-f
參數指定,編輯命令的格式為
/pattern/action
其中pattern
是正則表達式,action
是編輯操作。sed
程序一行一行讀出待處理檔案,如果某一行與pattern
匹配,則執行相應的action
,如果一條命令沒有pattern
而只有action
,這個action
將作用於待處理檔案的每一行。
表 32.5. 常用的sed命令
/pattern/p | 打印匹配pattern 的行 |
/pattern/d | 刪除匹配pattern 的行 |
/pattern/s/pattern1/pattern2/ | 查找符合pattern 的行,將該行第一個匹配pattern1 的字元串替換為pattern2 |
/pattern/s/pattern1/pattern2/g | 查找符合pattern 的行,將該行所有匹配pattern1 的字元串替換為pattern2 |
使用p
命令需要注意,sed
是把待處理檔案的內容連同處理結果一起輸出到標準輸出的,因此p
命令表示除了把檔案內容打印出來之外還額外打印一遍匹配pattern
的行。比如一個檔案testfile
的內容是
123 abc 456
打印其中包含abc
的行
$ sed '/abc/p' testfile 123 abc abc 456
要想只輸出處理結果,應加上-n
選項,這種用法相當於grep
命令
$ sed -n '/abc/p' testfile abc
使用d
命令就不需要-n
參數了,比如刪除含有abc
的行
$ sed '/abc/d' testfile 123 456
注意,sed
命令不會修改原檔案,刪除命令只表示某些行不打印輸出,而不是從原檔案中刪去。
使用查找替換命令時,可以把匹配pattern1
的字元串複製到pattern2
中,比如:
$ sed 's/bc/-&-/' testfile 123 a-bc- 456
pattern2
中的&
表示原檔案的當前行中與pattern1
相匹配的字元串,再比如:
$ sed 's/\([0-9]\)\([0-9]\)/-\1-~\2~/' testfile -1-~2~3 abc -4-~5~6
pattern2
中的\1
表示與pattern1
的第一個()
括號相匹配的內容,\2
表示與pattern1
的第二個()
括號相匹配的內容。sed
預設使用Basic正則表達式規範,如果指定了-r
選項則使用Extended規範,那麼()
括號就不必轉義了。
如果testfile
的內容是
<html><head><title>Hello World</title> <body>Welcome to the world of regexp!</body></html>
現在要去掉所有的HTML標籤,使輸出結果為
Hello World Welcome to the world of regexp!
怎麼做呢?如果用下面的命令
$ sed 's/<.*>//g' testfile
結果是兩個空行,把所有字元都過濾掉了。這是因為,正則表達式中的數量限定符會匹配儘可能長的字元串,這稱為貪心的(Greedy)[39]。比如sed
在處理第一行時,<.*>
匹配的並不是<html>
或<head>
這樣的標籤,而是
<html><head><title>Hello World</title>
這樣一整行,因為這一行開頭是<
,中間是若干個任意字元,末尾是>
。那麼這條命令怎麼改才對呢?留給讀者思考。