Bash脚本中的多行正则表达式XML替换(可能通过Perl)

时间:2015-12-28 16:57:59

标签: regex bash perl multiline

我有一个格式如下的XML文件。

我想利用步骤名称,其中包含字符" VM"在VM相关的步骤。当我看到" VM"在步骤名称中,我想替换用" VMname"提交的计算机名称。和计算机ID字段" VMid。"

我想要

<step sequence="106" name="Patch%20Baseline">
   <!-- No parameters accepted for baseline steps -->
   <target-set>
    <computer name="nameAndIDTarget" id="123" />
  </target-set>
 </step>
 <step sequence="110" name="Warning%3A%20Outdated%20VMware%20Tools%20Version">
  <target-set>
    <computer name="nameAndIDTarget" id="123" />
  </target-set>
 </step>

成为

<step sequence="106" name="Patch%20Baseline">
  <!-- No parameters accepted for baseline steps -->
  <target-set>
    <computer name="nameAndIDTarget" id="123" />
  </target-set>
</step>
<step sequence="110" name="Warning%3A%20Outdated%20VMware%20Tools%20Version">
  <target-set>
    <computer name="VMname" id="VMid" />
  </target-set>
</step>

这个函数将是bash脚本的一部分,所以如果通过Perl完成,我更喜欢单行或内联方法。我是Perl / Regex愚蠢的,无法理解到目前为止我见过的例子。

3 个答案:

答案 0 :(得分:2)

它没有回答问题的问题,但正确的做法是使用支持XML的工具,例如XMLStarlet

xmlstarlet ed -u '//step[contains(@name, "VM")]/target-set/computer/@name' -v VMname \
              -u '//step[contains(@name, "VM")]/target-set/computer/@id' -v VMid \
  <in.xml >out.xml

请注意,这假定使用默认命名空间;如果您的层次结构中的某个位置有xmlns="..."属性,则应编辑该问题以包含该属性。

答案 1 :(得分:0)

这是我的解决方案 - 在我看来,这对于单线程来说太复杂了。只需调用perl脚本就很容易了。

$vm = ;                                         # $vm is set to 1 only if s step sequence with `VM` in is detected
while(<>) {                                     # Loop through the file, line by line
    if(m!<step sequence=.* name="(.*VM.*)">!) { # Check for sequence name containing VM
        $vm = 1;
     }
     if($vm == 1 && m!<computer name!) {        # Output special VM name   
         print qq!    <computer name="VMname" id="VMid" />\n!;
         $vm = 0;                               # Reset the VM flag
     } else {
         print $_;                              # Otherwise print the input line
     }
}

答案 2 :(得分:-1)

你去吧

perl -pe 'if (m!<step .*name=".*VM!..m!</step>!){ if (m!<computer!){s/name=".*?"/name="VMname"/;s/id=".*?"/id="VMid"/} }' test.xml

如果进行投票的人不知道Perl魔法

,请留下参考资料

perldoc触发器