そのため、bashシェルスクリプトを介してXMLファイルを操作する必要がある作業があります。
次のように進んでください。
- XMLファイルの値を照会します。
- 値を取得し、それらを相互参照してリスト内の新しい値を見つけます。
- 他の要素の値を新しい値に置き換えます。
以下は、不要な情報が削除された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
。
これらのオプションは使用されないため、デフォルトでは
-n
各sed
入力行は出力として印刷されます(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/
パターン空間の最初の項目を 。regex
replacement
この
sed
コマンドはp
行を印刷します。