填充XML文件中定义的目标的Shell脚本

填充XML文件中定义的目标的Shell脚本,shell,Shell,假设有一个file.txt,其中的文本如下所述:- ABC EFG XYZ 在另一个xml中,定义了一个名为(compile)的空主体目标 . . . 从这里开始//直到EOF 壳 剧本 xyz 我需要一个shell脚本来填充定义的目标之间的内容。在执行脚本后,它应该如下面的output标签中所述。它将针对file.txt文件中写入的整个内容执行 输出:- <!-- ...preceding portions of input document... --> <proje

假设有一个file.txt,其中的文本如下所述:-

ABC
EFG
XYZ
在另一个xml中,定义了一个名为(compile)的空主体目标


.
.
.
从这里开始//直到EOF
壳
剧本
xyz
我需要一个shell脚本来填充定义的目标之间的内容。在执行脚本后,它应该如下面的output标签中所述。它将针对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... -->

componentName=“ABC”
componentName=“EFG”
componentName=“XYZ”
开始
壳
剧本
xyz

您可以使用
sed
while read-r
循环(在某种程度上)执行您正在尝试的操作。例如,您可以将xml文件的内容从第1行填充到带有

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"
(使用带有子字符串替换的参数展开,将关闭的
'/'
添加到
的开头

总而言之,您可以做如下操作:

#!/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>
$ cat f1
ABC
EFG
XYZ

$ cat another.xml
<project>
<compile>
start
shell
script
xyz
</compile>
</project>
$cat f1
基础知识
EFG
XYZ
$cat.xml
开始
壳
剧本
xyz
示例使用/输出

$ fillxml.sh

$ cat f3.xml
<someschema>
<targettag>
componentName="ABC"
componentName="EFG"
componentName="XYZ"
</targettag>
</someschema>
$ cat f3.xml
<project>
<compile>
componentName="ABC"
componentName="EFG"
componentName="XYZ"
start
shell
script
xyz
</compile>
</project>
$cat f3.xml
componentName=“ABC”
componentName=“EFG”
componentName=“XYZ”
开始
壳
剧本
xyz
如果您有任何疑问,请仔细查看并告诉我。

使用合适的XML解析器。有适合此工作的工具吗:

#!/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
!/bin/bash
#^^^^-重要,不是/bin/sh
#将输入文件读入数组

IFS=$'\n'read-r-d'-a如果有太多情况下这会表现不好。如果
也出现在CDATA节或注释中会怎样?如果它位于别名命名空间中会怎样?如果被替换的字符串之一需要转义为有效的XML会怎样?如果有人向该标记添加属性,使其成为
?同意。我不主张使用bash解析xml,因为您引用了所有的理由(因此在某种程度上,限定
)。对于这种有限的情况,当然,作为一种推广,解决方案的编号为no.thnx@DavidC.Rankin,但使用此解决方案,我还需要更改我的要求。一旦使用所有组件名称行构建最终xml,并且在您即将关闭目标时。我不想关闭标记,尽管我想在关闭ta之前复制更多文本rget和组件名称之后。您可以在命令中帮助复制f2中写入的特定内容中的文本吗。xml让我们说“开始”word是用f2.xml编写的,我想在创建f3.xml时,至少从该word复制到f3.xml中的EOF,直到componentName。当然,让我确保我理解,我看到问题被编辑了,让我看看在复制结束标记之前,我是否可以计算出您希望插入的其他文本。应该很简单,可以包含任何其他文本最后一个
componentName=“…”后面的文本
行,然后关闭标记。您是否要求将
targettag
更改为
compile
?需要哪些其他信息?如果唯一的区别是将
targettag
更改为
compile
,则不需要更改,只需运行
bash script.sh即可“
,它将使用
作为搜索和填充内容的标记。您还可以更改脚本,将输入、xml和输出文件名作为参数。在回答原始问题时,我的重点只是显示如何查找标记,插入
组件名=“…”
基于另一个文件的内容,最后是如何复制结束标记和文件的其余部分。
$ 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>
#!/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