特殊文字を含む大きなファイルがあります。そこに複数行のコードがあり、それをsed
に置き換えます。
この:
text = "\
------ ------\n\n\
This message was automatically generated by email software\n\
The delivery of your message has not been affected.\n\n\
------ ------\n\n"
これに変える必要があります:
text = ""
次のコードを試しましたが、うまくいきませんでした。
sed -i '/ text = "*/ {N; s/ text = .*affected.\./ text = ""/g}' /etc/exim.conf
何も置き換えず、エラーメッセージも表示しません。
私はそれで遊んでいますが、私が試みるすべてが機能しません。
Perlが救い出します:
Perl -i~ -0777 -pe 's/text = "[^"]+"/text = ""/g' input-file
-i~
はファイルを「インプレース」で編集し、バックアップコピーを残します-0777
は、行ごとではなく、ファイル全体を一度に読み取ります置換s///
はsedと同様に機能します(つまり、text = "
の後に二重引用符以外のすべてのものが二重引用符まで何度も続く)と一致しますが、この場合、ファイル全体で機能します。
パターンスペースを確認し、一致しない場合はN
ext行を引き続き取得する必要があります。
sed '/text = "/{ # if line matches text = "
:b # label b
$!N # pull in the next line (if not the last one)
/"$/!bb # if pattern space doesn't end with " go to label b
s/".*"/""/ # else remove everything between the quotes
}' infile
gnu sed
次のように書くことができます
sed '/text = "/{:b;$!N;/"$/!bb;s/".*"/""/}' infile
ただし、これはあまり効率的ではありません。範囲/text = "/,/"/
、最初の行を変更して残りを削除します。
sed '/text = "/,/"/{ # in this range
/text = "/!d # delete all lines not matching text = "
s/\\/"/ # replace the backslash with quotes (this is only
}' infile # executed if the previous d wasn't executed)
もう一度、gnu sed
ワンライナーとして書くことができます:
sed '/text = "/,/"/{/text = "/!d;s/\\/"/}' infile
個人的には、Perlでこれを行います。 "
を閉じる前に"
がないと想定できる場合は、次のようにできます。
Perl -0pe 's/(text\s*=\s*)".*?"/$1""/s' file
-0
はファイル全体を丸呑みし、メモリに読み込みます。 -p
は、「-e
」で指定されたスクリプトを適用した後、「すべての行を印刷する(ここでは、「行」はファイル全体になります)」という意味です。スクリプト自体は単純な置換演算子です。文字列text
に続いて0個以上の空白文字、=
、0個以上の空白文字(text\s*=\s*
)をキャプチャし、$1
として保存します。次に、キャプチャしたパターンと、見つかった最も短い引用符付きの文字列をパターン($1
)と""
に置き換えます。 s
フラグは、.
を改行に一致させます。