如何在文件的两个模式之间替换内容?


9

我有以下格式的文件:

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

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

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

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

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

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

:/<inputs>/norm vitd

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

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

我该如何实现?

Answers:


10

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

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

看到 :help sub-replace-expression

请注意,这keeppatterns可以防止substitute命令向搜索历史添加任何内容,并保留“最后的搜索模式寄存器”-请参见:help "/。这是很好的做法,以防止脚本用下面的命令修饰符不必要的修改Vim的全局状态keepaltkeepjumpslockmarkskeepmarks,和keeppatterns


5

Gary的另一种替代方法是:

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

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


4

这似乎至少在Unix系统上有效:

:/<inputs>/+1,/<\/inputs>/-1!cat foo.txt

它使用{range}!{filter}命令后从一个线过滤<inputs>之前,一个</inputs>通过外部程序cat foo.txt。在这种情况下,cat忽略其标准输入,因此原始行将被删除并由file的内容替换foo.txt

看到:

:help :range!
:help cmdline-ranges

2

我觉得宏将是一个更容易的方法。特别是,如果您有很多地方可以做同样的事情。

  1. 仅打开那两个文件。
  2. 现在,在第一个文件中,以qa,a为记录名称)开始记录。
  3. 搜索开始模式,按下来,然后按Ctrl- v,搜索结束模式,按起来。现在,选择要删除的零件。删除它。
  4. 使用maa标记名称)标记位置并保存文件。
  5. 通过:b2命令转到第二个文件,然后根据您的开始/结束条件选择零件。
  6. 回到该文件,按此键a。粘贴到那里p
  7. 再次搜索结束条件,并横切该部分以免再次点击它。
  8. 按退出编码q
  9. 重复次数40@a

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

1

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

这里的解决方案是有效的,但意图可能不是。如果XML并非经过精心处理,则标记中可能会出现转义符,CDATA或空格!

因此,vi中的命令中的xsltproc可以解决该问题。


该文件实际上不是正确的XML格式,但是实际上却没有充分记录的ini文件,具有这3个类似XML的标记。
kenorb '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.