複数行にわたるSED交換


11

私はこれらの3行を見つけようとしています:

<!--
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
-->

そしてそれらを次のものに置き換えます:

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

私がしようとすると

sudo sed -i 's:<!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->:<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />:' /myfile.xml

見つかりませんでした。\ nも挿入しようとしましたが、それでも機能しませんでした。

sudo sed -i 's:<!--\n <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />\n -->:<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />:' /myfile.xml

これらはエラーをスローせず、行のコメントを解除しません。どんなアドバイスでも感謝します!

回答:


6

sedは各行を順番に読み取るため、正しい方向に動かさない限り、複数行のパターンに一致することはありません。このNコマンドは、入力から1行を読み取り、それをパターンスペースに追加します。

sed -i -e '/^<!--$/ {
    N; /\n<Connector port="8009" protocol="AJP\/1\.3" redirectPort="8443" \/>$/ {
        N; /\n-->$/ {
            s/^<!--\n//; s/\n-->$//
        }
    }
}' /myfile.xml

おそらく、以外のコマンドが必要な場合はs、sedからawkまたはperlに切り替える必要があります。これは、より一般的な方法で複数行コメントに対処する、やや柔軟なPerlスニペットです。

perl -i -pe '
    if (/<!--/) { $_ .= <> while !/-->/;
        s[<!--\n(<Connector port="8009" protocol="AJP/1\.3" redirectPort="8443" />)\n-->][$1];
    }' /myfile.xml

6

Sedは行単位で動作します。複数のラインで動作するように作成することはできますが、そのようには設計されていません。そして、私の意見では、そのように使用しようとすると確実に表示されます。ただし、その方法を選択する場合は、おそらくレジスタを使用する必要があります。解決方法については、https://stackoverflow.com/questions/1251999/sed-how-can-i-replace-a-newline-nのソリューションのいくつかを確認してください。

この種のタスクでは、sedではなくperlを使用することを好みます(つまり、複数行指向です)。検索と置換(BEGIN...)の前に追加する必要のあるボイラープレートは明らかではありませんが、正規表現は私にはきれいに見えます。

perl -i.bak -pe 'BEGIN{undef $/;} s/<!--string-->/string/smg' file.xml

または、グループ化を使用して式を短くし、そこで正規表現を使用できるようにします。

perl -i.bak -pe 'BEGIN{undef $/;} s/<!--(string_or_regex)-->/\1/smg' file.xml

コメントマーカーとコメント解除するコードの間に改行がある場合とない場合の両方で機能します。

原作:

/programming/1030787/multiline-search-replace-with-perl


あなたの助けをありがとう、それは苦痛のようです、私は回避策を使用することにしました
Doug Molineux


1
  • /<\!--/ :一致する文字列
  • :X :これは分岐コマンド "b"のラベルです
  • /-->/ :一致する文字列
  • s@...@...@p :「<!-」、「->」を取り除いて結果を出力する
  • d :パターンスペースを削除して新しいサイクルを開始
  • N :/-> /と一致しない場合は、行を追加します
  • bX ::Xラベルへの分岐
  • p :/ <!-/と一致しない文字列を出力するだけです

sed -rn '
/<!--/ {
    :X
    /-->/ {
        s@<!--\s*(<.+/>)\s*-->@\1@p
        d
    }
    N
    bX
};p'

この2番目の方法は、通常の小さなサイズのテキストファイルの単純なコピー&ペーストの逐語的置換です(シェルスクリプトファイルが必要です)。

#!/bin/bash

# copy & paste content that you want to substitute

AA=$( cat <<\EOF | sed -z -e 's#\([][^$*\.#]\)#\\\1#g' -e 's#\n#\\n#g'
<!--
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
-->
EOF
)

BB=$( cat <<\EOF | sed -z -e 's#\([&\#]\)#\\\1#g' -e 's#\n#\\n#g'
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
EOF
)

sed -z -i 's#'"${AA}"'#'"${BB}"'#g' *.xml   # apply to all *.xml files

1)お返事ありがとうございます。2)コードスニペットのみを挿入することは実際には大丈夫ではありません。説明し、それが何をどのように行うかを説明した方がはるかに良いでしょう。
peterh-モニカを2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.