web-dev-qa-db-ja.com

複数行にわたるSED交換

私はこれらの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

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

9
Doug Molineux

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

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

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

原作:

https://stackoverflow.com/questions/1030787/multiline-search-replace-with-Perl

5
Eduardo Ivanec

SEDの複数行コマンドの説明は次のとおりです。 http://docstore.mik.ua/orelly/unix/sedawk/ch06_01.htm

お尻の痛みです。エドゥアルドのアドバイスに従い、Perl -i -p -e代わりに。

2
Hyppy
  • /<\!--/:一致する文字列
  • :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
mug896