sedで複数行にまたがった文字列を置換する方法

Bash

はじめに

sed コマンドで複数行にまたがったパターン置換を行いたい場合があります。

検証環境

$ uname -moi
x86_64 MacBookPro11,4 Darwin

$ bash -version | head -n 1
GNU bash, バージョン 5.0.11(1)-release (x86_64-apple-darwin18.6.0)

複数行にまたがったパターンの置換とは

sed は基本的にラインエディタの思想を受け継いでいるため、入力情報を1行ずつ受け取って処理を行います。

例えば、 % で囲まれた部分を空文字に置換するといった場合、合致パターンが1行で収まる場合は容易に置換できます。

$ echo 'xx%aaa%yyy'
xx%aaa%yyy

$ echo 'xx%aaa%yyy' | sed 's/%.*%//'
xxyyy

合致パターンが複数行にまたがったときにはうまく置換してくれません。

$ echo 'xxx%aaa
bbb%yyy'
xxx%aaa
bbb%yyy

$ echo 'xxx%aaa
bbb%yyy' | sed 's/%.*%//'
xxx%aaa
bbb%yyy

簡単に対処することができます。

-z オプションを使う

-z オプションを利用します。
これは sed のデフォルトの挙動である「行単位の処理」から「ヌル文字単位の処理」に挙動を切り替える、というオプションになります。

通常のテキストにヌル文字が入っていることはありませんので、これによりテキスト全体を読み込み、一度に置換するようになります。

$ echo 'xxx%aaa
bbb%yyy' | sed -z 's/%.*%//'
xxxyyy

ひとこと

注意しないといけない店として、通常は行単位に処理されていた sed 処理を全文字列を一度に処理おすることになるため、メモリ負荷が増えることになります。

あまりに巨大なファイルを処理する場合にはメモリ不足の注意が必要です。

Bash