sed または awk を使用して XML ファイルから検索および置換する

sed または awk を使用して XML ファイルから検索および置換する

そのため、bashシェルスクリプトを介してXMLファイルを操作する必要がある作業があります。

次のように進んでください。

  1. XMLファイルの値を照会します。
  2. 値を取得し、それらを相互参照してリスト内の新しい値を見つけます。
  3. 他の要素の値を新しい値に置き換えます。

以下は、不要な情報が削除されたXMLの例です。

<fmreq:fileManagementRequestDetail xmlns:fmreq="http://foobar.com/filemanagement">
      <fmreq:property>
         <fmreq:name>form_category_cd</fmreq:name>
         <fmreq:value>Memos</fmreq:value>
      </fmreq:property>
      <fmreq:property>
         <fmreq:name>object_name</fmreq:name>
         <fmreq:value>Correspondence</fmreq:value>
      </fmreq:property>
</fmreq:fileManagementRequestDetail>

object_nameの下の値要素から値を取得して相互参照し、form_category_cd値要素の下の値を新しい値に置き換える必要があります。

したがって、object_name ->値がCorrespondenceの場合、form_category_cd ->値はYYZでなければならない可能性があります。

問題は、私たちの運営チームが私たちが持っているツールだけを使用することを制限しているので、サーバーで利用可能なツールだけを使用できることです。 xmllintアップデートのための戦いがありましたが、後で拒否されました。私が使用しているバージョンは--xpathをサポートしていません。良い日にも問題があると確信しています。また、利用可能なバージョンは名前空間をサポートしていないため、xmllintは終了します。

私はsedを試しましたが、私が試したすべてのテスターはうまくいきましたが、正規表現が気に入らないようです。

正規表現:

(<fmreq\:name>object_name<\/fmreq\:name>)(?:\n\s*)(<fmreq\:value>)(.*)(<\/fmreq\:value>)

グループ#3を取得する必要がありますが、sedはそれを返しません。代わりにXMLファイルの内容全体を返します。

sed -e 's/\(<fmreq\:name>object_name<\/fmreq\:name>\)\(?:\n\s*\)\(<fmreq\:value>\)\(.*\)\(<\/fmreq\:value>\)/\3/' < c3.xml 

私はawk / gawkについてよく知らないので、それらも見つけようとしていますが、見つかった場合は解決策で開いています。

awk/gawkソリューションを持ちたいだけで、上司が古いawkファンなので彼を喜ばせるように努力したいのですが、大変なので得られるものを選びます。

今回も私は持っているツールを使う必要があり、新しいものをインストールすることができませんでした。

答え1

使用XMLスター:

$ xml ed -u '//fmreq:property[fmreq:name="object_name"]/preceding-sibling::fmreq:property/fmreq:name' -v YYZ file.xml
<?xml version="1.0"?>
<fmreq:fileManagementRequestDetail xmlns:fmreq="http://foobar.com/filemanagement">
  <fmreq:property>
    <fmreq:name>YYC</fmreq:name>
    <fmreq:value>Memos</fmreq:value>
  </fmreq:property>
  <fmreq:property>
    <fmreq:name>object_name</fmreq:name>
    <fmreq:value>Correspondence</fmreq:value>
  </fmreq:property>
</fmreq:fileManagementRequestDetail>

XPathの最初の部分はノードを//fmreq:property[fmreq:name="object_name"]探し、このビットは前のノードのノードを探します。<fmreq:name>object_name</fmreq:name>/preceding-sibling::fmreq:property/fmreq:name<fmreq:name><fmreq:property>

答え2

あなたのコマンドにいくつかの問題があると思いますsed

  • これらのオプションは使用されないため、デフォルトでは-nsed入力行は出力として印刷されます(sedコマンドで変更できます)。

  • 最後のパラメータはファイル名として認識されるため、< c3.xmlリダイレクトする必要はありません。sed

  • sedマルチラインマッチングには適していません。例を見るここ

あなたの例では、以下がうまくいくようです。

sed -n "/<fmreq:name>object_name<\/fmreq:name>/ {n;p}" c3.xml | sed "s/^\s*<fmreq:value>\(.*\)<\/fmreq:value>/\1/g"

またはsed一度だけ呼び出してください。

sed -n "/<fmreq:name>object_name<\/fmreq\:name>/ {n;s/^\s*<fmreq:value>\(.*\)<\/fmreq:value>/\1/g;p}" c3.xml

このコマンドの機能は次のように分類されます。

  • このオプションは、ライン処理後にパターンスペースを印刷しないように指示-nします。したがって、これを行うにはコマンドを明示的に使用する必要がsedあります。p

  • /regex/sed一致する行のコマンドのみを実行するように指示しますregex

  • このsedコマンドは、nパターン空間の内容を目的の値を含む次の入力行に置き換えます。

  • このsedコマンドは、s/regex/replacement/パターン空間の最初の項目を 。regexreplacement

  • このsedコマンドはp行を印刷します。

関連情報