我的文件格式如下:

<common>
fitnes=0
genetic=1
method=0
</common>
<inputs>
foo=bar
bar=foo
</inputs>
<limits>
balance=200.00
</limits>


,我想删除<inputs></inputs>之间的所有内容(不包括自行设置模式)并替换它以及来自另一个文件(例如foo.txt)的内容。换句话说,带有foo=barbar=foo的行将替换为其他内容。

它可能类似于删除多行匹配的方式,例如:

:g/<inputs/,/inputs>/d


,但是我不确定我应该替换d以便插入另一个文件的内容,但是我想保留匹配的模式。

类似的方法会是要删除html标签的内部内容,例如

:/<inputs>/norm vitd


,但是我不知道如何将文件中的内容添加到其中。

理想情况下,我正在尝试寻找一种衬纸,因为它将成为另一种脚本的一部分。

我该如何实现?

#1 楼

可以使用替换来替换具有以下表达式的结果的模式:

:keeppatterns %s;<inputs>\zs\_.\{-}\ze</inputs>;\=insert(readfile('test.txt'), '')


请参见:help sub-replace-expression

请注意,keeppatterns会阻止从任何内容添加到搜索历史记录并保留“最后一个搜索模式寄存器”的substitute命令-请参阅:help "/。最好的做法是防止脚本使用命令修改器keepaltkeepjumpslockmarkskeepmarkskeeppatterns不必要地修改Vim的全局状态。

#2 楼

Gary的另一种替代方法是:

:g/^<inputs>/+,/^<\/inputs>/-d|-r dummy


首先删除给定模式中的所有内容,然后使用:r命令从虚拟文件中读取数据。
现在,如果您需要从<input>/</input>模式之间的行中提取文件名,则会有点麻烦。

#3 楼

至少在Unix系统上,这似乎可行: {range}!{filter}。在这种情况下,<inputs>会忽略其标准输入,因此将删除原始行,并用文件</inputs>的内容替换。

请参见:

#4 楼

我觉得宏将是一种更简单的方法。
尤其是如果您有很多地方可以做同样的事情。在第一个文件中,以qa,开始录音(a是记录名称)。
搜索开始模式,按向下,然后按Ctrl-v,搜索结束模式,按向上。现在,选择要删除的零件。删除它。
使用ma标记位置(a是标记名称)并保存文件。
通过:b2命令转到第二个文件,并类似地根据您的开始/结束条件选择零件。
回到此文件,按a转到该点。通过p粘贴在那里。
再次搜索结束条件,并越过该部分以免再次击中它。
q退出重新编码。
40@a重复次数。


评论


感谢您的建议,这很好,但是在这种情况下无济于事,因为我正在寻找非交互式解决方案作为ex脚本的一部分,在该脚本中,我可以根据用户输入的参数指定要插入的文件。

– Kenorb
16-2-2在12:35

#5 楼

如果这是使用非XML工具解析XML的另一种尝试,请不要这样做。

此处的解决方案有效,但意图可能并非如此。如果XML并非来自严格控制的源,则标记中可能会包含转义符,CDATA或空格!

因此vi中的xsltproc命令可以处理该问题。

评论


该文件实际上不是正确的XML格式,但是实际上没有充分记录的ini文件具有这3个类似XML的标记。

– Kenorb
16-2-2在12:17