我有一个格式如下的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愚蠢的,无法理解到目前为止我见过的例子。
答案 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触发器