假设有一个file.txt,其中的文本写如下: -
ABC
EFG
XYZ
在另一个xml中,有一个名为(compile)的空体目标定义。
<project>
<compile>
.
.
.
start //from here till EOF
shell
script
xyz
</compile>
</project>
我需要一个shell脚本来填充定义的目标之间的内容。在执行脚本之后,它应该在输出标记中看起来如下所述。它将用于在file.txt文件中编写的整个内容。
输出: -
<!-- ...preceding portions of input document... -->
<project>
<compile>
componentName="ABC"
componentName="EFG"
componentName="XYZ"
start
shell
script
xyz
</compile>
</project>
<!-- ...remaining portions of input document... -->
答案 0 :(得分:1)
使用正确的XML解析器。 XMLStarlet是适合这项工作的一种工具:
#!/bin/bash
# ^^^^- important, not /bin/sh
# read input file into an array
IFS=$'\n' read -r -d '' -a pieces <file.txt
# assemble target text based on expanding that array
printf -v text 'componentName=%s\n' "${pieces[@]}"
# Read input, changing all elements named "compile" in the default namespace
# ...to contain our target text.
xmlstarlet ed -u '//compile' -v "$text" <in.xml >out.xml
答案 1 :(得分:0)
您可以使用sed
和while read -r
循环执行您尝试(在某种程度上)的操作。例如,您可以使用
<targettag>
sed -n "1, /^${ttag}$/p" "$xfn" > "$ofn" ## fill output to ttag
(其中xfn
是您的xml文件名,ofn
是您的输出文件名)
然后,您可以阅读文本文件中的所有值并添加componentName="
并附加"
:
while read -r line; do ## read each line in ifn and concatenate
printf "%s%s\"\n" "$cmptag" "$line" >> "$ofn"
done <"$ifn"
(其中ifn
是您的输入文件名)
最后,您可以使用以下命令将结束标记写入xml文件的末尾:
sed -n "/^${ttag/</<[\/]}$/, \${p}" "$xfn" >> "$ofn"
(使用带有子字符串替换的参数扩展将结束'/'
添加到<targettag>
的开头。
完全放弃,你可以做类似的事情:
#!/bin/bash
ifn="f1"
xfn="f2.xml"
ofn="f3.xml"
ttag="${1:-<targettag>}" ## set target tag
cmptag="componentName=\"" ## set string to prepend
sed -n "1, /^${ttag}$/p" "$xfn" > "$ofn" ## fill output to ttag
while read -r line; do ## read each line in ifn and concatenate
printf "%s%s\"\n" "$cmptag" "$line" >> "$ofn"
done <"$ifn"
## fill output from closing tag to end
sed -n "/^${ttag/</<[\/]}$/, \${p}" "$xfn" >> "$ofn"
输入文件
$ cat f1
ABC
EFG
XYZ
$ cat f2.xml
<someschema>
<targettag>
</targettag>
</someschema>
示例使用/输出
$ fillxml.sh
$ cat f3.xml
<someschema>
<targettag>
componentName="ABC"
componentName="EFG"
componentName="XYZ"
</targettag>
</someschema>
(您可以调整缩进以满足您的需求)
更改问题后添加
在添加start
标记后,处理从componentName="..."
到结尾处理所需的更改很简单。但是,单词start
的共性说明了为什么Charles的答案鼓励您使用XML工具而不是简单的脚本。为什么?如果单词“开始”&#39;在您的.xml
文件之前的任何其他位置发生在您的预期start
之前,脚本将因第一次出现start
而写入结尾。
也就是说,如果这是一个简单的开关转换而start
没有发生,那么对脚本的更改很容易实现所需的输出:
#!/bin/bash
ifn="f1"
xfn="another.xml"
ofn="f3.xml"
ttag="${1:-<compile>}" ## set target tag
cmptag="componentName=\"" ## set string to prepend
sed -n "1, /^${ttag}$/p" "$xfn" > "$ofn" ## fill output to ttag
## read each line in ifn and concatenate
while read -r line || [ -n "$line" ]; do
printf "%s%s\"\n" "$cmptag" "$line" >> "$ofn"
done <"$ifn"
## fill output from 'start' to end
sed -n "/^start/, \${p}" "$xfn" >> "$ofn"
输入文件
$ cat f1
ABC
EFG
XYZ
$ cat another.xml
<project>
<compile>
start
shell
script
xyz
</compile>
</project>
示例使用/输出
$ cat f3.xml
<project>
<compile>
componentName="ABC"
componentName="EFG"
componentName="XYZ"
start
shell
script
xyz
</compile>
</project>
仔细看看,如果您有疑问,请告诉我。