XMLタグの内容を置き換えるためにsedを使用する際に問題があります。

XMLタグの内容を置き換えるためにsedを使用する際に問題があります。

次のXMLフラグメントがあります。

<value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">+380554446363</value>
<value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">+380554446364</value>
<value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">+380554446365</value>

<value>以下を使用して、タグコンテンツをSHA-1ハッシュに置き換えようとしました。

cat test.xml | sed "s/>[+]\([0-9][0-9]*\)<\/value>/>+$(echo \\1 | sha1sum | cut -f1 -d' ')<\/value>/g"

見つかったすべてのケースが同じエラー値に置き換えられているため、失敗します。

期待される:

<value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">34df370575e3528b31daef8633cb539119a3b028</value>
<value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">d93767c769fd51bcf9eb25f95932559b24bae812</value>
<value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">20338c1f048bed553b6cce76eaf1d388ba7686f5</value>

得る:

<value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">+cbcac786fef5abeb39fe473ab6abe554978a8156</value>
<value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">+cbcac786fef5abeb39fe473ab6abe554978a8156</value>
<value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">+cbcac786fef5abeb39fe473ab6abe554978a8156</value>

私は何を間違えることができましたか?ティア。

答え1

sedXMLを使用または編集しないでくださいawkxmlPythonなどの適切なパーサーを使用してくださいxml.etree

input.xml:

<values>
    <value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">+380554446363</value>
    <value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">+380554446364</value>
    <value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">+380554446365</value>
</values>
#!/usr/bin/env python3
import hashlib
import xml.etree.ElementTree as ET

tree = ET.parse('input.xml')
root = tree.getroot()

for value in root:
    value.text = hashlib.sha256(value.text.encode('utf-8')).hexdigest()


tree.write('output.xml')

output.xml:

<values>
    <value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">4b2bdff20d17dc4ae7ad99937399530b39bd7a63f7348375c547d01565c11898</value>
    <value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">8d3b1452d83ef803f8043eaddbe2fc58b0fd42c8ad5abc554e78796548f75ddb</value>
    <value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">06bd986417875e536401306180c51b7ded4eeab179933e0026a103bc8dc9eee7</value>
</values>

答え2

sha1sum最初のSED正規表現一致ではなく、定数文字列 "\ \ 1"のSHA-1を評価します。

$ echo \\1 | sha1sum
cbcac786fef5abeb39fe473ab6abe554978a8156  -

シェルは、コマンド(この場合はsed)を実行する前に、さまざまな拡張(コマンドの置き換えなど)のすべてを実行します。したがって、皮が膨張する。

cat test.xml | sed "s/>[+]\([0-9][0-9]*\)<\/value>/>+$(echo \\1 | sha1sum | cut -f1 -d' ')<\/value>/g"

到着

cat test.xml | sed "s/>[+]\([0-9][0-9]*\)<\/value>/>+cbcac786fef5abeb39fe473ab6abe554978a8156<\/value>/g"

次に、2つのプロセスを実行します。 1つは実行中です。

cat test.xml

もう一つは実行中です。

sed "s/>[+]\([0-9][0-9]*\)<\/value>/>+cbcac786fef5abeb39fe473ab6abe554978a8156<\/value>/g"

最初のプロセスのSTDOUTは、2番目のプロセスのSTDINにパイプされます。

実行したい操作が機能するには、sed内から別の実行可能ファイルを実行できる必要がありますsed。私はそれができると信じていないので、sed他の方法でやるべきです。

を使用してこれを行うことができますsed。たとえば、これは1つの方法です。

for a in `cat test.xml | sed -E 's,^.*>(\+[0-9]+)<\/value>$,\1,'`; do echo "$a" | sha1sum | cut -f1 -d' '; done >2nd
cat test.xml | sed -E 's,>\+[0-9]+</value>$,>,' >1st
paste -d '' 1st 2nd | sed -E 's,$,</value>,'

また、期待される結果として提供されたSHA1の合計に基づいて、最初の一致文字列の括弧に「+」を含めませんでした。sed「+」を含めたかったのでこの部分も修正しました。

答え3

GNU sed 代替コマンドには、変更されたパターン/e 空間とも呼ばれる s/// の rhs である vash コードで実行される修飾子があります。

sed -E "
  s/'/&\\\\&&/g
  s:(<.*>)([+][0-9]+)(</value>.*):printf '%s%s%s' '\\1' \"\$(echo '\\2'|sha1sum|cut -d' ' -f1)\" '\\3':e
" test.xml

<value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">34df370575e3528b31daef8633cb539119a3b028</value>
<value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">d93767c769fd51bcf9eb25f95932559b24bae812</value>
<value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">20338c1f048bed553b6cce76eaf1d388ba7686f5</value>

答え4

次のシステムを使用する場合次にコンパイルcrypto 拡大する話せる機能:

xmlstarlet sel -N crypto='http://exslt.org/crypto' \
  -t -m '//value' -e '{name()}' -c '@*' -v 'crypto:sha1(.)' -b -n \
file.xml

出力:

<value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">3bacaac1e104d7bfde5ff462d461d3b4b917c037</value>
<value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">808b3e7bb8c8c7c06c328a082bac64205837531b</value>
<value id="1" creatorId="0" creationTime="1639487132" expirationTime="1639573532">8c31811a3b8d816f719ad5c78b58810b9b6cd4b7</value>

ここで、チェックサムは、改行を含むテキストでは計算されないため、目的の出力とは異なります。


xmlstarlet transform --show-ext 2>&1 | grep crypto私の最終出力で次を実行します。

{http://exslt.org/crypto}md4
{http://exslt.org/crypto}sha1
{http://exslt.org/crypto}md5
{http://exslt.org/crypto}rc4_decrypt
{http://exslt.org/crypto}rc4_encrypt

関連情報