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을 사용하거나 편집 하지 마십시오 awk. xmlPython과 같은 적절한 파서를 사용하십시오 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"

그런 다음 두 개의 프로세스를 실행합니다. 하나는 실행 중입니다.

cat test.xml

또 다른 하나가 실행 중입니다.

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

첫 번째 프로세스의 STDOUT은 두 번째 프로세스의 STDIN으로 파이프됩니다.

수행하려는 작업이 작동하려면 sed내에서 다른 실행 파일을 실행할 수 있어야 합니다 sed. 나는 그것이 이루어질 수 있다고 믿지 않으므로 sed다른 방법으로 해야 할 것입니다.

를 사용하여 이 작업을 수행할 수 있습니다 sed. 예를 들어 이는 한 가지 방법입니다.

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

관련 정보