Sed
sed(“stream editor”)是Unix 用於解析和轉換文字檔案的實用程式,它在各種作業系統上都有可用的移植版本。在許多情況下,它已被perl(或更早的AWK)取代,但在 shell 指令碼中進行簡單轉換時,sed 仍然保留了一些用途。
Sed 是面向行的 - 它一次處理一行 - 並允許正則表示式 匹配和替換。
sed 最常用的功能是s命令(“替換”或“thes///結構”),它將一個模式替換為另一個模式;這起源於早期的 ed,並在 perl 中保留了使用。
簡單來說
sed s/cat/dog/g in > out
將在檔案中的“cat”替換為“dog”in並將它輸出到檔案out;“g”表示“全域性”:替換所有匹配項,而不僅僅是給定行上的第一個匹配項。
人們通常希望使用單引號(' ')包圍模式以避免 shell 錯誤地解釋它
sed 's/cat/dog/g' in > out
一些實現要求表示式前面有-e如果有多個模式,人們無論如何都會希望使用它
sed -e 's/cat/dog/g' -e 's/meow/woof/g' in > out
Sed 也可以作為管道執行,接收標準輸入併發送到標準輸出。
對於複雜的模式,人們可能希望使用-r(GNU sed)或-E(BSD sed)開關以啟用“擴充套件正則表示式”,因為 sed 的預設轉義和正則表示式可能很難使用,特別是在轉義“(”時。
分組特別有用,使用 (…) 表示要匹配的組,並使用 \1, \2, …, \9 在替換模式中引用該編號組。例如,
sed -r 's/<(.*)>/<\1><\/\1>/g'
將 <a> 替換為 <a></a>。這允許簡單的欄位解析和處理,例如重新排列多個模式組。
除了使用s命令外,人們可以在 sed 中開發複雜的程式。
Sed 是面向行的 - 它一次處理一行,剝離尾隨的換行符。為了對多行進行操作,人們必須使用更復雜的結構,即N命令(將下一行新增到緩衝區),或H然後是g. 參見Sed 常見問題解答,第 5.10 節
對於將檔案中的所有行連線起來的簡單任務,最簡單的方法是使用tr實用程式
tr '\n' ' '
表示“用空格替換換行符”。請注意,sed(除了 GNU sed)有空格限制,因此任何將整個檔案連線成 sed 中的一行的操作都會將整個檔案儲存在記憶體中;而 tr 只從頭到尾處理輸入,因此沒有此類記憶體問題。
在一個表示式中,這可以寫成
tr '\n' ' ' < in > out
grep 和 tr 是有用的補充 - 前者選擇行,後者應用單字元轉換。例如,您可以使用 grep 選擇某些行,然後透過管道傳遞給 sed 來解析這些行。
AWK,尤其是Perl,是同類的高階語言,如果需要執行 sed 中難以完成的任務,可以使用它們作為替代方案。
POSIX 標準 sed 的命令列選項
- -n: 僅透過 p 命令產生輸出。
- -e script
- -f script-file
GNU sed 的命令列選項,超出了POSIX 標準 sed
- --version
- --help
- --quiet 和 --silent,除了 -n
- --expression=script
- --file=script-file
- -i[SUFFIX], --in-place[=SUFFIX]
- -l N, --line-length=N
- --posix
- -b, --binary
- --follow-symlinks
- -r, --regexp-extended
- -s, --separate
- -u, --unbuffered
BSD sed 的命令列選項(預設安裝在 macOS 上),超出了POSIX 標準 sed
- -E: 使用擴充套件正則表示式
- -a
- -i extension
- -l
連結
- 2 呼叫 在 sed 手冊中,gnu.org
- Unix sed(1) 手冊頁 在 man.cat-v.org 上
Sed 使用了一種特定版本的正則表示式,它與 grep 和 Perl 不同。Sed 涵蓋了 POSIX 基本正則表示式(另見正則表示式/Posix 基本正則表示式)。
sed 中可用的正則表示式功能包括 *, ., ^, $, [ ], [^ ],\( \),\n,\{i\}, \{i,j\} 和 \{i,\} 。
GNU sed 中作為 GNU 擴充套件可用的正則表示式功能包括 \+,\?,\,\b,\B,\w,\W,\s,\S,\`,\',\<,\>。此外還包括 \a(響鈴字元),\f(換頁),\n(換行),\r(回車),\t(水平製表符),\v(垂直製表符),\cx(Control-x),\dxxx(按十進位制 ASCII 值表示的字元),\oxxx(按八進位制 ASCII 值表示的字元),\xhh(按十六進位制 ASCII 值表示的字元)。
sed 支援的預定義字元類包括 [:alpha:], [:blank:], [:cntrl:], [:digit:], [:graph:], [:lower:], [:print:], [:punct:], [:space:], [:upper:] 和 [:xdigit:]。
sed 中不可用的正則表示式功能包括 Perl 元字元 \d,\D,\A 和 \Z。
連結
- 正則表示式 在 sed 手冊中,gnu.org
- 3.9 GNU 擴充套件用於正則表示式中的轉義,在 sed 手冊中,gnu.org
替換的單行示例
sed "s/concieve/conceive/" myfile.txt
- 替換每行中第一個出現的 "concieve"。
sed "s/concieve/conceive/g" myfile.txt
- 由於末尾有 "g",因此替換所有出現。
sed "s/concieve/conceive/g;s/recieve/receive/g" myfile.txt
- 執行兩個替換。
$ echo "abccbd" | sed "s/a\([bc]*\)d/\1/g"
bccb
- 使用 \( 和 \) 標記組,並使用 \1 在替換部分引用該組。
- 可能只適用於 GNU sed;需要驗證。
$ echo "abccbd" | sed -r "s/a([bc]*)d/\1/g"
bccb
- 在 GNU sed 中,它與前一個示例執行相同操作,只是使用 -r 開啟擴充套件正則表示式,消除了在 "(" 前新增反斜槓以指示分組的需要。
- -r 開關在 GNU sed 中可用,而在原始 Unix sed 中不可用。
$ echo "a b" | sed -r "s/a\s*b/ab/g"
ab
- 在 GNU sed 中,使用 "\s" 表示空格,並使用 "*" 使前一個字元組重複任意次數。需要 -r 在 GNU sed 中啟用擴充套件正則表示式。
sed "s/\x22/'/g" myfile.txt
- 在 GNU sed 中,將每個引號替換為單引號。\x22 指的是十六進位制 ASCII 值為 22 的字元,即引號。
$ echo Hallo | sed "s/hallo/hello/gi"
hello
- 忽略字元大小寫,因為末尾有 "i"。不保留大小寫,輸出 "hello" 而不是 "Hello"。
$ echo a2 | sed "s/[[:alpha:]]/z/g"
z2
- 使用 [[:alpha:]],它代表任何字母。請注意,字元類在手冊中列為 "[:alpha:]",帶單引號 "[".
- 將日期格式轉換為另一種格式
$ echo "03/11/2015 23:54:03" | sed -r "s/([0-9]+)\/([0-9]+)\/([0-9]+)/\3-\2-\1/g"
2015-11-03 23:54:03
Sed 不支援在 ".*?" 表示式中看到的非貪婪匹配。在 Unix shell 指令碼中,您可以使用 Perl 單行命令來模擬帶有非貪婪匹配的 sed
$ echo "abcbbc" | perl -pe "s/a.*?c/ac/"
acbbc
$ perl -pe "s/a.*c/ac/" # without the non-greedy "?"
ac
- GNU sed 使用者手冊(單頁) at gnu.org
- sed(1) OS X 手冊頁 at developer.apple.com
- Unix sed(1) 手冊頁 在 man.cat-v.org 上
- Sed 常見問題解答 at sed.sourceforge.net
- Sed 例項,第一部分 at ibm.com
- 維基百科:sed