Lesen von Daten aus einer Eingabedatei und Platzieren der Daten in entsprechenden Feldern in einer XML-Datei

Lesen von Daten aus einer Eingabedatei und Platzieren der Daten in entsprechenden Feldern in einer XML-Datei

Ich habe eine Eingabedatei und eine XML-Datei.

Eingabedatei-

/user/sht
227_89,45_99
/user/sht1
230_90
/user/sht2
441_50

Die Datei enthält abwechselnde Zeilen mit Pfad und Position.

xml-Datei-

<aaa><command name="move">
<domain>
<path></path>
<positions></positions>
</domain>
<domain>
<path></path>
<positions></positions>
</domain>
<domain>
<path></path>
<positions></positions>
</domain>
</command>
</aaa>

Ich muss ein Skript schreiben, um die unten erforderliche Ausgabe-XML zu erhalten, und dann einige Befehle ausführen, wobei ich die unten stehende XML als Eingabe verwende.

<aaa><command name="move">
<domain>
<path>/user/sht</path>
<positions>227_89,45_99</positions>
</domain>
<domain>
<path>/user/sht1</path>
<positions>230_90</positions>
</domain>
<domain>
<path>/user/sht2</path>
<positions>441_50</positions>
</domain>
</command>
</aaa>

Ich habe versucht, Zeile für Zeile aus der Eingabedatei zu extrahieren und in die XML-Datei einzufügen, aber das Problem besteht darin, dass jedes Vorkommen <path>durch die erste Eingabezeile ersetzt wird.

Verwende GNU Bash 4.1.2.

Antwort1

Mit einem einzigen GNU- sedSkript könnten Sie beispielsweise Folgendes tun:

sed -n '/<aaa>/,/<.aaa>/!{H;d}
G;:a
s_>\(</path>.*\n\)\n\([^\n]*\)_>\2\1_
s_>\(</positions>.*\n\)\n\([^\n]*\)_>\2\1_;
ta;P;s/.*\n\n/\n/;h' input.txt input.xml

Die erste Zeile sammelt alle Zeilen aus der ersten Datei im Hold-Puffer.

Anschließend wird für jede Zeile der zweiten Datei der Hold-Buffer mit angehängt G. Handelt es sich um ein pathoder positionswird das erste Segment des Hold-Buffers mit einem der beiden sBefehle in die Tags verschoben.

In jedem Fall wird die Zeile gedruckt ( P) und entfernt ( s/.*\n\n/\n/) und der Rest der Ersetzungsliste wird für den nächsten Zyklus zurück in den Haltepuffer verschoben ( h).

Antwort2

Shell-Skript, das Ihre Anforderungen abdeckt

#!/bin/bash
count=0          ## counting lines
while read var
do
    occurance=$[$count/2+1];                  ## check nth occurance of search path/position from file
if [ $((count%2)) -eq 0 ];                ## If counting even replace path values else replace position values
then
    perl -pe 's{<path>*}{++$n == '$occurance' ? "<path>'$var'" : $&}ge' xml > xml1
else
    perl -pe 's{<positions>*}{++$n == '$occurance' ? "<positions>'$var'" : $&}ge' xml > xml1
fi
yes|cp xml1 xml
    count=$[$count +1]
done <./input
rm xml1 

Antwort3

Verwenden Sie GNU sed und das Format für XML wie gezeigt:

sed -e '
   /<domain>/,/<\/domain>/!b
   /<\(path\|positions\)><\/\1>/!b
   s//<\1>/
   R input_file
' XML_file |
sed -e '
   /<\(path\|positions\)>.*/N
   s//&\n<\/\1>/
   s/\n//g
'

Ergebnisse

<aaa><command name="move">
<domain>
<path>/user/sht</path>
<positions>227_89,45_99</positions>
</domain>
<domain>
<path>/user/sht1</path>
<positions>230_90</positions>
</domain>
<domain>
<path>/user/sht2</path>
<positions>441_50</positions>
</domain>
</command>
</aaa>

Antwort4

In der Shell:

echo '<aaa><command name="move">'
echo '<domain>'

while true
do read v || break
   echo "<path>$v</path>"
   read v || break
   echo "<positions>$v</positions>"
done < /path/to/YourInputFile

echo '</domain>
</command>
</aaa>'

verwandte Informationen