跳轉到內容

Sed

100% developed
來自華夏公益教科書,開放的書籍,開放的世界

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
[編輯 | 編輯原始碼]

greptr 是有用的補充 - 前者選擇行,後者應用單字元轉換。例如,您可以使用 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

連結

正則表示式

[編輯 | 編輯原始碼]

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 "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
[編輯 | 編輯原始碼]
[編輯 | 編輯原始碼]
華夏公益教科書