2015-02-10 205 views
1

我试图在特定模式后仅使用sed执行N行上的替换。sed:模式匹配后在N行上执行替换

看看sed手册页,似乎应该可以使用addr1,+ N语法。但我无法让它工作。

<data> 
    <variable>DebuggerItem.Count</variable> 
    <value type="int">2</value> 
</data> 
<data> 
    <variable>Version</variable> 
    <value type="int">1</value> 
</data> 

我正在执行的替换查找此标记中的数字,并将它们递增1.它如下所示。

sed -r 's/([ ]*<value type=)\"(int)\"(>)([0-9]*)(.*)/echo "\1\\"\2\\"\3$((\4+1))\5"/ge' filename 

我现在要限制更换只是在N行包含“DebuggerItem.Count”一前一后。在我目前的情况下,N是1,但我有另一个例子,我想在匹配后的5行中执行此操作,因此N将为5.

它可能可以用更复杂的替换来执行,但理想情况下,我想了解更多有关使用sed地址的信息。

注意:我在搜索替换中的双引号引起了一些麻烦,因为我需要将它们转义为以下回显。所以搜索替换有点复杂。我很抱歉。

+2

你的大问题是'xml'数据不知道行,所以这种方法是错误的。如果不是现在,我敢打赌你会在不久的将来与它斗争。您应该尝试使用'xml'解析器。 – Birei 2015-02-10 14:29:49

+0

我很欣赏你在说什么@Birei sed可能不是手头工作的最佳工具,因为我正在流编辑一个xml文件。但我仍然认为使用addr1,+ N语法用法的问题是有效的。如果能够帮助提供答案,我很乐意将问题重新格式化以移除<, /, "and >的实例。 – 2015-02-10 14:42:07

回答

1

我同意@Birei;不要用sed来做到这一点。如果在无害的地方添加了新行或重新排序节点,没有人希望您的XML工具中断,而这正是如果您为任务使用基于行的工具时会发生的事情。事情会以可怕的方式打破,他们可能会在你忘记你在那里建立了什么以及为什么后两个月做到这一点。

有很多工具可以解析和转换XML。例如,xmlstarlet你的问题可以解决这样的:

xmlstarlet ed -u '//data[variable="DebuggerItem.Count"]/value' -x '. + 1' filename.xml 

这里//data[variable="DebuggerItem.Count"]/value是一个XPath表达式选择的value子节点一个data节点,其variable子节点有"DebuggerItem.Count"值在文档中的任意位置,. + 1是另一个XPath表达式,表示当前节点的值加1。请参阅here

如果你是死心塌地使用sed,放心,它会回来咬你,你可以限制你的s命令应用到三行你喜欢这个文件中找到DebuggerItem.Count后:

#    new bit   from here it's the same as before. 
#  vvvvvvvvvvvvvvvvvvvvvvvv vvvvvvv 
sed -r '/DebuggerItem\.Count/,+3 s/([ ]*<value type=)\"(int)\"(>)([0-9]*)(.*)/echo "\1\\"\2\\"\3$((\4+1))\5"/ge' foo.xml 
+0

谢谢@Wintermute。非常感激。感谢您提供xmlstartlet替代方案,以及对我原来错误的问题的工作答案。 – 2015-02-10 14:52:46