用于填充 XML 文件中定义的目标的外壳脚本



>假设有一个文件.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

你可以用sedwhile 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"出现在.xmlstart文件的其他任何位置,则脚本将因第一次出现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>

查看一下,如果您有问题,请告诉我。

最新更新