>假设有一个文件.txt其中的文本如下所述:
ABC
EFG
XYZ
在另一个 xml 中,定义了一个名为 (compile) 的空体目标。
<project>
<compile>
.
.
.
start //from here till EOF
shell
script
xyz
</compile>
</project>
我需要一个 shell 脚本来填充定义的目标之间的内容。执行脚本后,它应该在输出标记中如下所示。它将为写入文件.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... -->
使用正确的 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=%sn' "${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
你可以用sed
和while read -r
循环(在某种程度上)做你正在尝试的事情。例如,您可以使用从第 1 行到<targettag>
的 xml 文件的内容填充临时文件
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>
(您可以根据需要调整缩进)
更改问题后的添加
添加componentName="..."
标记后处理从start
到结束的写入所需的更改很简单。但是,单词start
的共性说明了为什么 Charles 的答案鼓励您使用 XML 工具而不是简单的脚本。为什么?如果单词"start"出现在.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>
查看一下,如果您有问题,请告诉我。