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

时间:2016-05-24 14:42:11

标签: shell

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

2 个答案:

答案 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)

您可以使用sedwhile read -r循环执行您尝试(在某种程度上)的操作。例如,您可以使用

将第1行xml文件内容的临时文件填充到<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>

仔细看看,如果您有疑问,请告诉我。