sed 串流編輯器:批次修改文字的利器 文章首圖

sed 串流編輯器:批次修改文字的利器

sed 串流編輯器:批次修改文字的利器

在 Linux 系統管理與自動化腳本開發中,文字處理是不可或缺的一環。雖然 grep 擅長搜尋,awk 精於欄位分析,但若談及「就地修改」或「串流替換」,sed (Stream Editor) 無疑是最具威力的工具之一。它能在不開啟編輯器的情況下,即時對檔案內容進行新增、刪除、取代與轉換,是系統管理員與 DevOps 工程師的必備技能。本文將深入解析 sed 的核心用法,並提供在 Ubuntu 22.04 / Debian 12 環境下可直接執行的實戰範例。

sed 的核心概念與基本語法

sed 的工作原理是逐行讀取輸入資料,根據指定的指令進行處理,並將結果輸出。其基本語法結構如下:

sed [選項] '{指令}' [檔案名稱]

其中,{指令}sed 的靈魂,通常由「地址」與「動作」組成。地址用於指定要處理的行的範圍,若省略則預設處理所有行;動作則指定對該行執行什麼操作,最常見的是 s (substitute,取代)。

基礎取代操作

讓我們建立一個測試檔案 test.txt,內容如下:

echo -e "Hello World\nThis is a test file.\nHello Linux" > test.txt
cat test.txt

輸出結果:

Hello World
This is a test file.
Hello Linux

1. 單行取代

若我們想把第一行的 Hello 改為 Hi,可以使用以下指令:

sed '1s/Hello/Hi/' test.txt

這裡 1 代表第一行,s 是取代動作,/ 是分隔符號。執行後會輸出修改後的內容,但原檔案並未被修改:

Hi World
This is a test file.
Hello Linux

2. 全域取代

若檔案中有多个 Hello,且我們希望全部取代,需加上 g (global) 參數:

sed 's/Hello/Hi/g' test.txt

輸出結果:

Hi World
This is a test file.
Hi Linux

3. 就地修改檔案

上述範例僅輸出到終端機。若需直接修改原檔案,必須使用 -i (in-place) 選項。在 GNU sed(Linux 預設版本)中,通常不需要在 -i 後接副檔名;而在 macOS 的 BSD sed 中則需要。為了相容性,建議在 Linux 上直接寫 -i

sed -i 's/Hello/Hi/g' test.txt
cat test.txt

此時 test.txt 的內容已永久變更。

進階應用:正規表示式與行號

sed 支援基礎正規表示式。例如,刪除檔案中的空行:

sed '/^$/d' test.txt

這裡 /^$/ 匹配從行首 ^ 到行尾 $ 的空字串,d 代表刪除 (delete)。

若要刪除特定範圍的行,例如刪除第 2 到第 3 行:

sed '2,3d' test.txt

常見問題與注意事項

在使用 sed 時,新手常會遇到以下兩個問題,請務必注意:

1. 特殊字元與分隔符號的衝突

sed 預設使用 / 作為分隔符號。若取代字串中包含 /(例如檔案路徑 /usr/bin),會導致語法錯誤。此時可改用其他字元作為分隔符號,例如 |#

# 錯誤範例:會報錯
# sed 's/usr/bin//usr/local/bin/g' test.txt

# 正確範例:改用 # 作為分隔符號
sed 's#/usr/bin#/usr/local/bin#g' test.txt

2. -i 選項的系統差異

如前所述,sed -i 的行為在不同作業系統上有差異。在 Ubuntu/Debian 的 GNU sed 中,sed -i 's/a/b/' file 會直接修改檔案。但在 macOS 或 BSD 系統中,-i 後面必須接一個副檔名(即使為空字串),否則 sed 會將下一個參數視為副檔名,導致檔案被錯誤地命名。

在 Linux 環境下,若擔心誤刪原檔案,建議初次使用時先不加 -i,確認輸出結果正確後,再加上 -i 執行。

小結

sed 是一款強大且高效的串流編輯工具,透過簡單的指令組合,即可實現複雜的文字批次處理任務。本文介紹了基本的取代、刪除、就地修改以及處理特殊字元的方法。掌握 sed 不僅能提升日常系統維護的效率,更是編寫自動化腳本時的關鍵技能。建議讀者多利用 test.txt 進行練習,熟悉各種選項與正規表示式的搭配,將能更得心應手地應對各種文字處理挑戰。