sed
編程範型 | 指令碼 |
---|---|
設計者 | 李·E·麥克馬洪 |
面市時間 | 1974年 |
實作語言 | C |
網站 | 无 |
啟發語言 | |
ed | |
影響語言 | |
Chomski, Perl, AWK |
sed(意為流編輯器,源自英語「stream editor」的縮寫)是一個使用簡單緊湊的程式語言來解析和轉換文字Unix實用程式。
sed由貝爾實驗室的李·E·麥克馬洪於1973年至1974年開發, [1] 並且現在大多數作業系統都可以使用。 [2] sed基於互動式編輯器ed(「editor」,1971)和早期qed(「quick editor」,1965-66)的指令碼功能。sed是最早支援正規表示式的工具之一,至今仍然用於文字處理,特別是用於替換命令。用於純文字字串操作和「流編輯」的常用工具還有AWK和Perl 。
歷史
[編輯]sed是為命令列處理資料檔案而構建的早期Unix命令之一,首次出現在Version 7 Unix中 。[3]它很自然地演變成為流行的grep命令的後繼。[4] 最初的動機與grep(g/re/p)的替換類似,因此稱為「g/re/s」。[3] 考慮到這樣的話還會出現針對每個命令的專用程式,例如g/re/d,李·E·麥克馬洪編寫了一個通用的面向行的流編輯器,該編輯器後來成為了sed。[4] sed的語法,特別是把/
用於模式匹配,把s///
用於替換,起源於sed的前身ed(當時ed很常用)[4] 而且正規表示式語法影響了其他一些語言,特別是ECMAScript和Perl。後來,更強大的語言AWK問世,這些工具相互補充,讓通過shell指令碼完成強大的文字處理成為可能。sed和AWK常被認為Perl的祖先和靈感來源,並且影響了Perl的語法和語意,尤其影響了匹配和替換運算子。
GNU sed添加了一些新功能,包括檔案的就地編輯 。Super-sed 是sed的擴充版本,包含與Perl相容的正規表示式。sed的另一變體minised ,最初埃里克·雷蒙把4.1BSD sed通過逆向工程寫成,目前由René Rebe維護。在GNU計劃基於新的GNU正規表示式庫編寫了新版本的sed之前,GNU計劃一直使用minised。當前minised包含一些BSD sed的擴充,但不像GNU sed那樣功能豐富。它的優點是速度快,占用的主記憶體少。它用於嵌入式系統,是Minix提供的sed版本。
工作模式
[編輯]sed是一個面向行的文字處理實用程式:它從輸入流或檔案中逐行讀取文字到一個稱為模式空間 的內部緩衝區。每讀一行開始一個迴圈 。對於模式空間,sed會應用sed指令碼 指定的一個或多個操作。sed實現了一種程式語言,其中包含大約25個指定文字操作的命令 。對於每個輸入行,在執行指令碼之後,sed通常輸出模式空間(由指令碼修改的行),然後從下一行再次開始迴圈。其他指令碼結束行為可通過sed選項和指令碼命令獲得,例如d
刪除模式空間,q
退出,N
立即將下一行添加到模式空間,等等。因此,sed指令碼對應於迴圈體,迴圈體遍歷流的行,其中迴圈本身和迴圈變數(當前行號)是隱式的並由sed維護。
可以在命令列上指定sed指令碼( -e
選項),也可以從單獨的檔案中讀取( -f
選項)。sed指令碼中的命令可以採用行號或正規表示式的作為位址 。該位址確定決定命令何時執行。例如,2d
將僅在第二個輸入行上執行d
(刪除)命令(列印除第二個輸入行之外的所有行),而/^ /d
將刪除以空格開頭的所有行。一些單獨的特殊緩衝區,即保持空間,可以由幾個sed命令使用,用於在迴圈之間保持和累積文字。sed的命令語言只有兩個變數(「保持空間」和「模式空間」)和類似GOTO的分支功能;然而,這種語言是圖靈完備的,[5][6] 用深奧sed指令碼甚至寫得出推箱子、打磚塊[7]、西洋棋[8]和俄羅斯方塊[9]等遊戲。
為輸入流的每一行執行一次主迴圈,在輸入的每一行上計算sed指令碼。sed指令碼的每一行都是模式-動作對,指示著要匹配的模式和要執行的操作,可以將其重新組合為條件語句。因為主迴圈、工作變數(模式空間和保持空間)、輸入和輸出流以及預設操作(複製行到模式空間、列印模式空間)是隱式的,所以可以編寫簡潔的單行程式。例如,以下sed程式:
10q
將列印輸入的前10行,然後停止。
用法
[編輯]替換命令
[編輯]下面的範例顯示了sed用於替換的典型(也是最常見的)用法。這種用法確實是sed的最初動機:[4]
sed 's/regexp/replacement/g' inputFileName > outputFileName
在某些版本的sed中,表達式的前面必須加上-e
,以表示後面跟著一個表達式。s
表示替換,而g
表示全域,這意味著行中的所有匹配項都將被替換。要搜尋的正規表示式(即pattern)放在第一個分隔符號(此處為斜槓)之後,而要替換成的字串跟在第二個分隔符號後面。斜槓(/
)是傳統的符號,起源於ed中的「搜尋」字元,但其實在pattern和替換文字中都未出現的任何其他符號都可以用作分隔符號,使其可讀性更強;這有助於避免「傾斜牙籤症候群」。
替換命令源自ed中的搜尋-替換,實現了簡單的解析和模板化 。regexp
提供模式匹配和通過子表達式儲存文字的功能,而replacement
可以是純文字,也可以是包含「完全匹配」&
,或第n 個子表達式(從\1
到\9
)這種特殊跳脫序列的格式字串。例如, sed -r "s/(cat|dog)s?/\1s/g"
用「cat」或「dog」替換所有出現的「cats」或「dogs」,且不重覆複製出原文內已有的「s」:在正規表示式中,(cat|dog)
是第一個(也是唯一)儲存的子表達式,格式字串中的\1
將其替換到輸出里。
其他sed命令
[編輯]除了替換之外,使用大約25個sed命令可以進行其他形式的簡單處理。例如,下面使用d 命令刪除空行或只包含空格的行:
sed '/^ *$/d' inputFileName
本例使用了下列正規表示式元字元(sed支援所有正規表示式):
- 脫字元(
^
)匹配行首。 - 美元符號(
$
)匹配行尾。 - 星號(
*
)匹配前一個字元零次或多次出現。
可以有很複雜的sed結構,讓sed用作一種簡單但高度專業化的程式語言。例如,可以通過使用標籤(冒號後跟字串)和分支指令b
來管理控制流程。指令b
後跟有效的標籤名稱,將把處理流程移動到該標籤後面的塊。
sed用作過濾器
[編輯]在Unix下,sed通常用作管道中的過濾器:
$ generateData | sed 's/x/y/g'
也就是說,諸如「generateData」之類的程式生成資料,然後用sed把x替換成y。例如:
$ echo xyz xyz | sed 's/x/y/g'
yyz yyz
基於檔案的sed指令碼
[編輯]將幾個sed命令(每行一個命令)放入指令碼檔案(例如subst.sed
)中然後使用-f
選項從檔案中執行命令(例如s/x/y/g
)通常很有用:
sed -f subst.sed inputFileName > outputFileName
可以在指令碼檔案中放置任意數量的命令,使用指令碼檔案也可以避免shell跳脫或替換的問題。
這樣的指令碼檔案可以直接從命令列執行,方法是在其前面加上一個包含sed命令的"shebang行",並為該檔案分配可執行權限。例如,可以使用以下內容建立檔案subst.sed
:
#!/bin/sed -f
s/x/y/g
然後,當前使用者可以使用chmod
命令使檔案可執行:
chmod u+x subst.sed
然後可以直接從命令列執行該檔案:
subst.sed inputFileName > outputFileName
就地編輯
[編輯]GNU sed中引入的-i
選項允許就地編輯檔案(實際上,在後台建立了一個臨時輸出檔案,然後將原始檔案替換為臨時檔案)。例如:
sed -i 's/abc/def/' fileName
範例
[編輯]Hello, world! 例子
[編輯]# convert input text stream to "Hello, world!"
s/.*/Hello, world!/
q
這個「Hello, world!」指令碼位於檔案(如script.txt)中,並使用sed -f script.txt inputFileName
呼叫,其中「inputFileName」是輸入文字檔案。指令碼將「inputFileName」第1行更改為「Hello, world!」然後退出,在sed退出之前列印結果。第1行後的任何輸入行都不會被讀取,也不會被列印。唯一的輸出是「Hello, world!」。
這個例子強調了sed的許多關鍵特性:
- sed是獨一無二的。沒有其他「Hello, world!」例子與之相似。
- 典型的sed程式相當簡短。
- sed指令碼可以有注釋(以
#
符號開頭的行)。 s
(替換)命令是最重要的sed命令。- sed允許使用
q
(退出)等命令進行簡單編程。 - sed使用正規表示式,例如
.*
(任何字元的零個或多個)。
其他簡單的例子
[編輯]下面是各種sed指令碼;可以把它們作為參數傳遞給sed,或者放入一個單獨的檔案並通過-f
執行或通過使指令碼本身可執行來執行。
要把檔案中某個單詞(例如IRC密碼)替換為「REDACTED」,並儲存結果:
sed -i s/yourpassword/REDACTED/ ./status.freenode.log
要刪除包含「yourword」一詞的所有行( 位址 為「/yourword/」):
/yourword/ d
要刪除所有「yourword」這個詞:
s/yourword//g
要同時從檔案中刪除兩個單詞:
s/firstword//g
s/secondword//g
為了在一行表示前面的範例,比如在命令列輸入時,可以通過分號連接兩個命令:
sed "s/firstword//g; s/secondword//g" inputFileName
多行處理範例
[編輯]在下一個範例中,sed(通常僅在一行上工作)會在某一行的後一行以一個空格打頭的情況下刪除換行符。 請考慮以下文字:
This is my dog, whose name is Frank. This is my fish, whose name is George. This is my goat, whose name is Adam.
下面的sed指令碼會將上面的文字轉換為以下文字。請注意,該指令碼僅影響以空格開頭的輸入行:
This is my dog, whose name is Frank. This is my fish, whose name is George. This is my goat, whose name is Adam.
使用的指令碼是:
N s/\n / / P D
這段指令碼應按如下理解:
- (
N
)將下一行添加到模式空間; - (
s/\n / /
)尋找一個換行符後跟一個空格,替換為一個空格; - (
P
)列印模式空間的頂行; - (
D
)從模式空間中刪除頂行並再次執行指令碼。
這可以通過分號在一行中表示出來:
sed 'N; s/\n / /; P; D' inputFileName
限制和替代方案
[編輯]雖然sed具有簡單性和局限性,但對於大量用途而言,它的功能已經足夠強大。對於更複雜的處理,可以使用更強大的語言,如AWK或Perl或者PowerShell。雖然使用保持緩衝區理論上可以進行任意複雜的轉換,但如果轉換行的方式比正規表示式提取和模板替換更複雜,則使用一般會使用上面提到的更強大的語言。
相反,對於更簡單的操作,grep (列印匹配模式的行),head(列印檔案的第一部分),tail(列印檔案的最後部分)和tr(翻譯或刪除字元)等專門的Unix實用程式通常更可取。對於設計用於執行的特定任務,此類專用實用程式通常比較一般的解決方案(如sed)更簡單、清晰和快速。
ed/sed命令和語法繼續用於衍生程式,例如文字編輯器vi和vim。sam/ssam與ed/sed類似,其中sam是Plan 9編輯器,ssam是它的流介面,其功能類似於sed。
注釋
[編輯]- ^ 在命令列使用中,表達式周圍的引號不是必需的,只有在shell不會將表達式解釋為單個字(標記)時才需要。由於指令碼
s/x/y/g
沒有歧義,所以generateData | sed s/x/y/g
工作正常。然而,為了清楚起見,通常是要寫引號的,特別是對於有空格的時候(例如,'s/x x/y y/'
)。大多數情況下,使用單引號是為了避免shell將$
解釋為shell變數。使用雙引號,如"s/$1/$2/g"
,是為了讓shell替換命令列參數或其他shell變數。
參考文獻
[編輯]- ^ The sed FAQ, Section 2.1. [2013-05-21]. (原始內容存檔於2018-06-27).
- ^ The sed FAQ, Section 2.2. [2013-05-21]. (原始內容存檔於2018-06-27).
- ^ 3.0 3.1 McIlroy, M. D. A Research Unix reader: annotated excerpts from the Programmer's Manual, 1971–1986 (PDF) (技術報告). CSTR. Bell Labs. 1987 [2018-11-10]. 139. (原始內容存檔 (PDF)於2019-11-30).
- ^ 4.0 4.1 4.2 4.3 On the Early History and Impact of Unix. [2018-11-10]. (原始內容存檔於2017-09-07).
A while later a demand arose for another special-purpose program, gres, for substitution: g/re/s. Lee McMahon undertook to write it, and soon foresaw that there would be no end to the family: g/re/d, g/re/a, etc. As his concept developed it became sed…
- ^ Implementation of a Turing Machine as Sed Script. [2018-11-10]. (原始內容存檔於2018-02-20).
- ^ Turing.sed. [2018-11-10]. (原始內容存檔於2018-01-16).
- ^ The $SED Home - gamez. [2009-04-20]. (原始內容存檔於2006-02-08).
- ^ bolknote/SedChess. GitHub. [2018-11-10]. (原始內容存檔於2018-12-02).
- ^ Sedtris, a Tetris game written for sed. [2018-11-10]. (原始內容存檔於2018-12-02).
擴充閱讀
[編輯]- 貝爾實驗室的第八版(約1985年)Unix sed(1)手冊頁(頁面存檔備份,存於網際網路檔案館)
- GNU sed(1)手冊頁
- Dale Dougherty & Arnold Robbins. sed & awk 2nd. O'Reilly. March 1997 [2018-11-10]. ISBN 1-56592-225-5. (原始內容存檔於2018-11-02).
- Arnold Robbins. sed and awk Pocket Reference 2nd. O'Reilly. June 2002 [2018-11-10]. ISBN 0-596-00352-8. (原始內容存檔於2018-11-11).
- Peter Patsis. UNIX AWK and SED Programmer's Interactive Workbook (UNIX Interactive Workbook). Prentice Hall. December 1998 [2018-11-10]. ISBN 0-13-082675-8. (原始內容存檔於2020-04-09).
- Daniel Goldman. Definitive Guide to sed. EHDP Press. February 2013 [2018-11-10]. ISBN 978-1-939824-00-4. (原始內容存檔於2018-01-29).
- Sourceforge.net(頁面存檔備份,存於網際網路檔案館) ,sed FAQ(2003年3月)
外部連結
[編輯]教程
[編輯]- Sed - An Introduction and Tutorial(頁面存檔備份,存於網際網路檔案館), by Bruce Barnett
- SED -- A Non-interactive Text Editor (1974)(頁面存檔備份,存於網際網路檔案館), by Lee E. McMahon
- 31+ Examples For Sed Linux Command In Text Manipulation(頁面存檔備份,存於網際網路檔案館), by Mokhtar Ebrahim
- Sed教學(頁面存檔備份,存於網際網路檔案館)
範例
[編輯]- Major sources for sed scripts, files, usage
- Roger Chang's SED and Shell Scripts (2012)(頁面存檔備份,存於網際網路檔案館)
- Top 'sed' commands – Usage examples
- Sed command examples in Unix & Linux(頁面存檔備份,存於網際網路檔案館)
其他連結
[編輯]- GNU sed首頁(包括GNU sed手冊)
- sed the Stream Editor(2004)(頁面存檔備份,存於網際網路檔案館) (Eric Pement)
- sed-users Yahoo討論組(頁面存檔備份,存於網際網路檔案館)