在Vim中查找并替换单行的部分内容

11

在vim中,大多数替换命令都会对整行或一组行执行操作,但我希望只在一行的一部分上执行此操作(从光标到行尾或两个标记之间)。

示例

this_is_a_sentence_that_has_underscores = this_is_a_sentence_that_should_not_have_underscores

进入

this_is_a_sentence_that_has_underscores = this is a sentence that should not have underscores

这个任务对整行来说很容易完成,只需使用:s/_/ /g命令,但是如果仅对等号后面的内容执行替换操作,就会更加困难。

:substitution 命令能否对一行的一半执行操作?


重复的问题:https://dev59.com/hH7aa4cB1Zd3GeqPwu-K? - Nishant
我不认为这是一个重复问题,尽管问题标题相似,另一个问题正在寻找一个正则表达式的答案(如被接受的答案所示),而我想知道是否有一种方法可以使它与行的特定内容无关(即某种vim移动或在同一行上两个标记之间)。 - Scott
是的,有点相似。您可能还想查看那里的答案。我认为目前在Vim中无法进行部分行编辑。即使是可视选择替换也适用于整行。 - Nishant
2个回答

13

我能想到两种解决方案。

第一种选择,使用前/后列匹配原子\%>123c\%<456c

在您的示例中,以下命令仅在第二个单词中,在第42列和第94列之间替换下划线:

:s/\%>42c_\%<94c/ /g

选项二,使用可视区域匹配原子\%V

在您的示例中,可视选择第二个长单词,退出可视模式,然后执行以下替换:

:s/\%V_/ /g

这些正则表达式组件的说明分别在:h /\%c:h /\%V中记录。


1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Scott

8

环视

你的问题中已经有一个重要线索:

只替换等号后面的内容。

这通常意味着使用正向先行断言,\@<=

:%s/\(=.*\)\@<=_/ /g

这意味着匹配所有在以下模式=.*之后的_。由于所有的前瞻和后顾都是零宽度,所以它们不会占用匹配空间,替换也很简单。
注意:这相当于perl中的(?<=...)。请参见:h perl-patterns

\zs怎么样?

\zs将在某个点设置匹配的起始位置。表面上看起来正是所需的。然而,\zs不能正确地工作,因为它首先匹配\zs之前的模式,然后是以下模式。这意味着只有一个匹配。另一方面,后顾匹配\@<=之后的部分,然后“向后查找”以确保匹配有效,这使得它非常适合多重替换场景。
应该注意的是,如果可以使用\zs,它不仅易于输入,而且更加高效。
注意:\zs就像perl语言中的\K

还有其他方法?!?

如@glts所提到的,您可以使用其他零宽度原子来基本“锚定”模式。以下是一些常见方法的列表:
  • \%>a - 在标记'a之后
  • \%V - 匹配可视区域内
  • \%>42c - 匹配第42列之后
使用这些方法的可能缺点是它们需要您设置标记或计算列数。这没有什么问题,但它意味着替换可能会受到副作用的影响,因此重复替换可能无法正常工作。
有关更多帮助,请参见:
:h /\@<=
:h /zero-width
:h perl-patterns
:h /\zs

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