У меня есть входной файл и 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, но проблема в том, что каждое вхождение <path>
заменяется первой входной строкой.
Использую GNU bash 4.1.2.
решение1
С помощью одного sed
скрипта GNU вы можете сделать что-то вроде
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
. Если это path
или , positions
первый сегмент буфера удержания перемещается внутрь тегов с помощью одной из двух s
команд.
В любом случае строка печатается ( P
) и удаляется ( s/.*\n\n/\n/
), а то, что осталось от списка замены, перемещается обратно в буфер хранения для следующего цикла ( h
).
решение2
Скрипт оболочки, который будет соответствовать вашим требованиям
#!/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
решение3
Используем 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>
решение4
В ракушке :
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>'