我有一个输入文件和一个 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
使用一个 GNUsed
脚本你可以做类似的事情
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
Shell 脚本将满足您的要求
#!/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>'