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


9

特殊文字が含まれている大きなファイルがあります。そこに私が置き換えたい複数行のコードがあり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

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

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


sed他のツールを使用する必要がありますか、それとも開いていますか?ブロックの"中にいることはできますtext=か?text = あなたのファイルに他のケースがある可能性はありますか?常に4行のテキストがありますか、それともそれ以上/少なくなることがありますか?
terdon

できればsed、またはCentOSサーバーにインストールする必要のないもの。すぐに
使える

@terdon text = フォルダーには他にはありませんtext = ""。ファイルには891行のコードがあります。SO、それは他のテキストを尊重する必要があります。
–blade19899

ファイルを上書きしますか、それとも出力を変更しますか?
joH1 2016

@Moonstroke上書きなし。それはちょうど私の質問で見られるように-にテキストを置き換える必要がありますtext = ""。私の質問で見たように。
blade19899

回答:


15

Perlが救い出します:

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

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


5

パターンスペースを確認し、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

3

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

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

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


補正は、-00段落全体ではなく、ファイル(読み込み参照)。引用符で囲まれたテキストに空白行が含まれている場合、正規表現は一致しません。
グレン・ジャックマン、2016

@glennjackmanああ!私は常にそれらを混同します。。これが、余分な段落を追加して実行することで実際にダブルチェックした理由perl -00ne 'print;exit'です。そして、私はまだ間違ったものを私の答えに入れました!ありがとう、修正しました。
terdon
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.