Sed

**sed**（意為**流編輯器**，源自英語「stream editor」的縮寫）是一個使用簡單緊湊的程式語言來解析和轉換文字 Unix 實用程式。

sed 由貝爾實驗室的李・E・麥克馬洪於 1973 年至 1974 年開發， 
並且現在大多數作業系統都可以使用。 sed 基於互動式編輯器 ed（「editor」，1971）和早期 qed（「quick editor」，1965-66）的指令碼功能。sed 是最早支援正規表示式的工具之一，至今仍然用於文字處理，特別是用於替換命令。用於純文字字串操作和「流編輯」的常用工具還有 AWK 和 Perl 。

## 歷史

sed 是為命令列處理資料檔案而構建的早期 Unix 命令之一，首次出現在 Version 7 Unix 中 。它很自然地演變成為流行的 grep 命令的後繼。 最初的動機與 grep（g/re/p）的替換類似，因此稱為「g/re/s」。 考慮到這樣的話還會出現針對每個命令的專用程式，例如 g/re/d，李・E・麥克馬洪編寫了一個通用的面向行的流編輯器，該編輯器後來成為了 sed。 sed 的語法，特別是把 `/` 用於模式匹配，把 `s///` 用於替換，起源於 sed 的前身 ed（當時 ed 很常用） 而且正規表示式語法影響了其他一些語言，特別是 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 的分支功能；然而，這種語言是圖靈完備的， 用深奧 sed 指令碼甚至寫得出推箱子、打磚塊、西洋棋和俄羅斯方塊等遊戲。

為輸入流的每一行執行一次主迴圈，在輸入的每一行上計算 sed 指令碼。sed 指令碼的每一行都是模式 - 動作對，指示著要匹配的模式和要執行的操作，可以將其重新組合為條件語句。因為主迴圈、工作變數（模式空間和保持空間）、輸入和輸出流以及預設操作（複製行到模式空間、列印模式空間）是隱式的，所以可以編寫簡潔的單行程式。例如，以下 sed 程式：

```
10q
```

將列印輸入的前 10 行，然後停止。

## 用法

### 替換命令

下面的範例顯示了 sed 用於替換的典型（也是最常見的）用法。這種用法確實是 sed 的最初動機：

在某些版本的 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 支援所有正規表示式）：

* 脫字元（ `^` ）匹配行首。
* 美元符號（ `$` ）匹配行尾。
* 星號（ `*` ）匹配前一個字元零次或多次出現。

可以有很複雜的 sed 結構，讓 sed 用作一種簡單但高度專業化的程式語言。例如，可以通過使用標籤（冒號後跟字串）和分支指令 `b` 來管理控制流程。指令 `b` 後跟有效的標籤名稱，將把處理流程移動到該標籤後面的塊。

### sed 用作過濾器

在 Unix 下，sed 通常用作管道中的過濾器：

也就是說，諸如「generateData」之類的程式生成資料，然後用 sed 把 _x_ 替換成 _y_。例如：

### 基於檔案的 sed 指令碼

將幾個 sed 命令（每行一個命令）放入指令碼檔案（例如 `subst.sed`）中然後使用 `-f` 選項從檔案中執行命令（例如 `s/x/y/g`）通常很有用：

可以在指令碼檔案中放置任意數量的命令，使用指令碼檔案也可以避免 shell 跳脫或替換的問題。

這樣的指令碼檔案可以直接從命令列執行，方法是在其前面加上一個包含 sed 命令的 "shebang 行"，並為該檔案分配可執行權限。例如，可以使用以下內容建立檔案 `subst.sed`：

然後，當前使用者可以使用 `chmod` 命令使檔案可執行：

然後可以直接從命令列執行該檔案：

### 就地編輯

GNU sed 中引入的 `-i` 選項允許就地編輯檔案（實際上，在後台建立了一個臨時輸出檔案，然後將原始檔案替換為臨時檔案）。例如：

## 範例

### Hello, world! 例子

這個「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」，並儲存結果：

要刪除包含「yourword」一詞的所有行（ _位址_ 為「/yourword/」）：

要刪除所有「yourword」這個詞：

要同時從檔案中刪除兩個單詞：

為了在一行表示前面的範例，比如在命令列輸入時，可以通過分號連接兩個命令：

### 多行處理範例

在下一個範例中，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。

 

## 注釋

## 參考文獻

## 擴充閱讀

* 貝爾實驗室的第八版（約 1985 年）Unix sed（1）手冊頁（頁面存檔備份，存於網際網路檔案館）
* GNU sed（1）手冊頁
* Dale Dougherty & Arnold Robbins. sed & awk 2nd. O'Reilly. March 1997 [2018-11-10]. ISBN1-56592-225-5. （原始內容存檔於 2018-11-02）.
* Arnold Robbins. sed and awk Pocket Reference 2nd. O'Reilly. June 2002 [2018-11-10]. ISBN0-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]. ISBN0-13-082675-8. （原始內容存檔於 2020-04-09）.
* Daniel Goldman. Definitive Guide to sed. EHDP Press. February 2013 [2018-11-10]. ISBN978-1-939824-00-4. （原始內容存檔於 2018-01-29）.
* Sourceforge.net（頁面存檔備份，存於網際網路檔案館） ，sed FAQ（2003 年 3 月）

## 外部連結

* `sed`– 命令與工具（Commands & Utilities）參考，單一 UNIX® 規範第 7 期，由國際開放標準組織發布

### 教程

* 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 討論組（頁面存檔備份，存於網際網路檔案館）

## 參見

* Unix 實用程式列表
* AWK
* tr
* PowerShell