sed(Stream Editor)是 Linux 文本處理「三劍客」之一,以行為單位流式處理文本,零拷貝、高效能,是 Shell 腳本、日誌分析、配置管理、CI/CD 管道不可或缺的利器。本文從核心語法切入,深度解析替換、刪除、插入、模式空間/保持空間進階技巧,並提供生產級實戰範例庫。
sed [選項] '腳本命令' 文件...
sed [選項] -f 腳本文件 文件...
sed [選項] -e '命令1' -e '命令2' 文件...
| 選項 | 作用 |
|---|---|
-n | 靜默模式:不自動輸出模式空間,**需配合 p 命令顯式輸出** |
-e | 指定多條編輯命令(命令行模式) |
-f | 從文件讀取編輯命令(腳本化推薦) |
-r / -E | 使用擴展正則表達式 (ERE),減少轉義 |
-i [後綴] | 原地修改文件(可選備份後綴,如 -i.bak)⚠️ 生產環境必備份 |
-s | 將多文件視為獨立流而非單一連續流處理 |
[地址範圍]命令[參數]
# 地址可為:行號、正則 /pattern/、$ (最後行)、範圍 1,10 /start/,/end/
# 命令單字母,大小寫敏感
| 命令 | 功能 | 典型用法 |
|---|---|---|
s | 替換 | s/舊/新/flags flags: g(全行), i(忽略大小寫), p(輸出), w 文件 |
d | 刪除行 | 1d /^$/d /pattern/d |
p | 列印行 | sed -n '1,5p' sed -n '/error/p' |
a | 行後追加 | 2a 新行內容 (需字面換行或 \n) |
i | 行前插入 | 2i 新行內容 |
c | 整行替換 | 2c 新內容替換第2行 |
y | 字符轉換 | y/abc/ABC/ (逐字符映射,長度必須等) |
q | 退出 | 10q 處理完第10行退出 |
Q | 靜默退出 | 不輸出模式空間 |
= | 輸出行號 | sed -n '/pattern/=' |
w | 寫入文件 | /pattern/w matched.txt |
r | 讀入文件 | 5r /etc/hostname 第5行後插入文件內容 |
h/H | 複製/追加到保持空間 | 進階多行處理核心 |
g/G | 從保持空間取回/追加 | 配合 h/H 實現跨行操作 |
x | 交換模式/保持空間 | 進階技巧 |
n/N | 讀取下一行到模式空間 | 多行模式匹配核心 |
b | 分支跳轉 | b label 條件分支 |
t | 條件分支(上次 s 成功) | 替換成功則跳轉 |
s 深度掌握
# 任意字符作分隔符,避免正則/替換內容含斜線需大量轉義
sed 's|/etc/nginx|/opt/nginx|g'
sed 's@https://@https://@g'
sed 's#/usr/local#/opt#g'
g:全行所有匹配(預設僅首個)i / I:忽略大小寫p:替換成功則輸出該行(配合 -n)w file:替換成功的行寫入文件e:將替換結果作為命令執行(GNU sed 扩展,慎用)
# 交換兩欄
echo "a b" | sed 's/\(.*\) \(.*\)/\2 \1/' # 輸出: b a
# 保留關鍵字,修改其前後
sed -E 's/(ERROR|WARN)/[\1]/g' log.txt # [ERROR] [WARN]
# 引用整個匹配 & (僅替換字符串中有效)
sed 's/pattern/&_suffix/g'
# 行號範圍
sed '10,20s/old/new/g' # 第10-20行
sed '10,$s/old/new/g' # 第10行到結尾
sed '1~2d' # 刪除奇數行 (GNU sed: 起始行+步長)
# 正則範圍
sed -n '/START/,/END/p' # 輸出 START 到 END 之間的行(含邊界)
sed '/^$/d' # 刪除空行
sed '/^[[:space:]]*#/d' # 刪除註釋行
# 多條件組合
sed -e '/^$/d' -e '/^#/d' # 刪除空行和註釋行
sed '/pattern1/{/pattern2/d}' # 包含 pattern1 的行中刪除 pattern2
sed 內部維護兩個緩衝區:
# 輸入文件:
# line1 \
# line2 \
# line3
# line4
sed ':a; /\\$/N; s/\\\n//; ta' file
# 解析:
# :a 定義標籤 a
# /\\$/N 當前行以\結尾 -> 讀取下一行追加到模式空間(含換行符)
# s/\\\n// 刪除 \ 和 換行符
# ta 替換成功(即有續行) -> 跳轉標籤 a 繼續檢查
# 結果: line1 line2 line3\nline4
sed '1!G;h;$!d' file
# 1!G 非第一行 -> 追加保持空間到模式空間(換行分隔)
# h 複製模式空間到保持空間(覆蓋)
# $!d 非最後行 -> 刪除模式空間(不輸出), 循環讀取下一行
# 最後行: 模式空間含所有行逆序 -> 自動輸出
# 修改 nginx 埠號
sed -i 's/^\(listen\s\+\)80;/\18080;/' /etc/nginx/nginx.conf
# 批量替換多個配置文件
find /etc/app/conf -name "*.conf" -exec sed -i 's/db_host=localhost/db_host=10.0.1.50/' {} +
# 提取 ERROR 級別日誌並脫敏 IP
sed -n '/ERROR/p' app.log | sed -E 's/[0-9]{1,3}(\.[0-9]{1,3}){3}/XXX.XXX.XXX.XXX/g'
# 統計各 HTTP 狀態碼出現次數
sed -n 's/.*"HTTP\/1\.[01]" \([0-9]{3}\) .*/\1/p' access.log | sort | uniq -c | sort -rn
# DOS/Windows (CRLF) -> Unix (LF)
sed 's/\r$//' dos.txt > unix.txt
# 或
sed -i 's/\r//g' file.txt
# CSV 欄位提取 (第 2, 4 欄)
sed -E 's/^([^,]*),([^,]*),([^,]*),([^,]*).*/\2,\4/' data.csv
# 在包含 "server {" 的行後插入多行配置
sed -i '/server {/a\
listen 8080;\
server_name example.com;\
root /var/www/html;\
' nginx.conf
# 刪除前 5 行 (跳過標題)
sed -i '1,5d' data.csv
# 刪除最後 3 行 (去除尾部統計)
# 需知總行數或用 tac 反轉
tail -n +4 data.csv | head -n -3 > clean.csv # 更簡潔替代方案

-i 必備份:sed -i.bak 's/old/new/' file,生產環境零容忍。精通 sed,即掌握了 Linux 文本處理的「手術刀」。從日誌清洗到配置自動化,從單行替換到多行重組,sed 以極簡語法承載極強表達力。建議將常用模式封裝為腳本庫(-f 模式),納入版本控制,讓文本處理可複用、可審計、可測試。