Чтение данных из входного файла и размещение данных в соответствующих полях в xml

У меня есть входной файл и файл xml.

входной файл-

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

В файле есть альтернативные строки, содержащие путь и позицию.

xml файл-

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

Мне нужно написать сценарий, чтобы получить требуемый xml-файл, а затем запустить несколько команд, используя указанный ниже xml в качестве ввода-

<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>

Я попытался извлечь построчно из входного файла и поместить это в xml, но проблема в том, что каждое вхождение заменяется первой строкой ввода.

Использование GNU bash 4.1.2.

-1
29.05.2017, 15:57
5 ответов

С помощью одного сценария GNU sed вы можете сделать что-то вроде

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

Первая строка собирает все строки из первого файла в буфере хранения.

Затем для каждой строки второго файла к буферу хранения добавляется G. Если это путь или позиции, первый сегмент буфера хранения перемещается внутри тегов с помощью одной из двух команд s.

В любом случае строка печатается (P) и удаляется (s/.*\n\n/\n/), а то, что осталось от списка замены, перемещается обратно в буфер хранения для следующего цикла (h).

0
28.01.2020, 05:12

В оболочке:

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>'
0
28.01.2020, 05:12

Используя GNU sed и формат XML, как показано:

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
'

Результаты

<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>
0
28.01.2020, 05:12

Сценарий оболочки, отвечающий вашим требованиям

#!/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 
0
28.01.2020, 05:12

Обратите внимание, что XML (, а также HTML )не являются обязательной структурой с«1 тегом на 1 строку»-он может иметьнесколькоразных тегов на] однустроку.

В таком случае я бы предложилPythonрешение:

заполнить _xml.pyскрипт:

import collections, xml.etree.ElementTree as ET

tree = ET.parse('yourxmlfile.xml') # <- specify your actual xml file name
root = tree.getroot()

with open('input.txt', 'r') as f:
    d = collections.defaultdict(list)
    for k,l in enumerate(f.read().splitlines()):
        if k % 2 == 0:  # treating each 2nd line as `positions` value
            d['path'].append(l)
        else:
            d['positions'].append(l)

    # iterating through `path`/`positions` node pairs
    for k, nodes in enumerate(zip(root.findall('.//path'), root.findall('.//positions'))):
        nodes[0].text = d['path'][k]        # setting `path` value
        nodes[1].text = d['positions'][k]   # setting `positions` value
    tree.write('result.xml')                # write to the result file

Использование:

python fill_xml.py

Содержание result.xml:

<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>
0
28.01.2020, 05:12

Теги

Похожие вопросы