使用vim替换标签之间的所有字符

8

我需要将所有 <filename>...</filename> 标签内的 / 字符替换为 \。

文件中有大约 2,000 个这些标签,我只需要替换标签内的 / 字符。

我该怎么做?


@ewok 这个问题与其他数百个与编辑器相关的问题有何不同之处? - deviousdodo
@ewok:已经相当明确地确定了,vim问题(特别是像这样的正则表达式问题)完全属于“程序员常用的软件工具”类别,在faq中明确列为“主题”的范畴。 - jkerian
3个回答

11

编辑:鉴于新的信息,下面的替换可能会起作用:

:%s/<filename>\zs.\{-}\ze<\/filename>/\=substitute(submatch(0), '\/', '\', 'g')/ 

解释:

  • %s:替换整个文件
  • /<filename>:匹配开始的模式和静态文本
  • \zs:匹配文本的开始
  • .\{-}:任意字符,非贪婪
  • \ze:匹配文本的结束
  • <\/filename>/:目标标记和模式的结束
  • \=:将替换结果作为vim表达式进行求值
  • substitute(submatch(0), '\/', '\', 'g')/: 将匹配文本中所有的/替换为\

原始回答:

我假设你是指XML风格的标签。我会首先视觉选择要操作的区域,然后使用\%V正则表达式原子只在该选择区域上操作。

vit:s!\%V/!\\!g

这应该可以解决问题。请注意,在按下:时,vim将自动为视觉选择添加一个范围,实际的替换命令看起来像:

:'<,'>s!\%V/!\\!g

谢谢,但这只适用于实际选定的标记,而不是所有标记中,可以这样做吗? - Oletros
正确。这是你可能想在你的问题中更明显的一个细节。 - Randy Morris

2

假设我们可以假定标签位于单独的一行,那么解决方法如下:

注意 输入^M时,请使用C-vC-m(在Windows上请使用C-qC-m

:g/<filename>/norm! /filename>/e^Mvity:let @"=substitute(@", '/', '\\', "g")^Mgvp

嗯,按照兰迪提供的提示,在模式中使用 \%V 使得它更简单:

:g/<filename>/norm! /filename>/e^Mvit:s#\%V/#\\#g^M

我测试过了,哇。现在我来解释一下,请稍等。

  1. :g/<filename>/ - 对于每一行包含 <filename> 的内容
  2. norm! - 执行普通命令(忽略映射)
  3. /filename/eEnter 跳转到开放标签的结尾
  4. vit - 在可视模式下选择该标签内的文本
  5. :s#\%V/#\\#gEnter - 在可视选区上执行替换操作(将 \ 替换为 /

0

VIM有一个陡峭的学习曲线,正则表达式也是如此。我相信这个命令会做到这一点。你必须用'\'转义每个字符。

:%s/\//\\/g

谢谢,但这将替换更多的 /,而我只需要替换<filename>...</filename>内部的 /。 - Oletros
哦,我的错,你只是想在标签中切换路径。我不知道正则表达式,可以试试看这个教程:http://www.thatsquality.com/articles/how-to-match-and-replace-content-between-two-html-tags-using-regular-expressions - Noah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接