web-dev-qa-db-ja.com

複数行のコードをsedに置き換える方法は?

特殊文字を含む大きなファイルがあります。そこに複数行のコードがあり、それを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

何も置き換えず、エラーメッセージも表示しません。

私はそれで遊んでいますが、私が試みるすべてが機能しません。

9
blade19899

Perlが救い出します:

Perl -i~ -0777 -pe 's/text = "[^"]+"/text = ""/g' input-file
  • -i~はファイルを「インプレース」で編集し、バックアップコピーを残します
  • -0777は、行ごとではなく、ファイル全体を一度に読み取ります

置換s///はsedと同様に機能します(つまり、text = "の後に二重引用符以外のすべてのものが二重引用符まで何度も続く)と一致しますが、この場合、ファイル全体で機能します。

15
choroba

パターンスペースを確認し、一致しない場合はNext行を引き続き取得する必要があります。

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
5
don_crissti

個人的には、Perlでこれを行います。 "を閉じる前に"がないと想定できる場合は、次のようにできます。

Perl -0pe 's/(text\s*=\s*)".*?"/$1""/s' file

-0はファイル全体を丸呑みし、メモリに読み込みます。 -pは、「-e」で指定されたスクリプトを適用した後、「すべての行を印刷する(ここでは、「行」はファイル全体になります)」という意味です。スクリプト自体は単純な置換演算子です。文字列textに続いて0個以上の空白文字、=、0個以上の空白文字(text\s*=\s*)をキャプチャし、$1として保存します。次に、キャプチャしたパターンと、見つかった最も短い引用符付きの文字列をパターン($1)と""に置き換えます。 sフラグは、.を改行に一致させます。

3
terdon