如何在vim中非捕获搜索和替换

cal*_*ofr 5 regex vim

我正在尝试学习如何使用vim的正则表达式,我正在尝试进行搜索和替换.我有这样的事情:

aaaaaaa&sometext&...
aaaaaaaanothertext
Run Code Online (Sandbox Code Playgroud)

(as实际上是行开头的空格,我不知道如何在这里打印)

我想替换第一次出现的&& &,并保持everyting其他不变.我正在使用\%(...\)非捕获模式,如此处所示,但a模式仍然被捕获.我正在使用:%s/\%(^a*\)&/& &/gc,我得到:

aaaaaaaa& aaaaaaaa&sometext&...
aaaaaaaaanothertext
Run Code Online (Sandbox Code Playgroud)

我不明白为什么.我也尝试过用组替换:%s/\%(^a*\)\(&\)/\1 \1/gc,但是后来我得到了:

& &sometext&...
aaaaaaaanothertext
Run Code Online (Sandbox Code Playgroud)

因此,似乎该组实际上被忽略了组处理(因为第一组是在搜索模式上&),但仍然在搜索模式上捕获.

所以,长话短说,取代命令我必须使用来自:

aaaaaaa&sometext&...
Run Code Online (Sandbox Code Playgroud)

至:

aaaaaaa& &sometext&...
Run Code Online (Sandbox Code Playgroud)

Jon*_*ink 6

我想替换第一次出现&with & &,并保持其他所有内容

使用替换命令:

:s/&/& &/
Run Code Online (Sandbox Code Playgroud)

另一个提示:默认情况下,Vim视为(文字字符,而不是组的开头.

very magic如果您希望正则表达式更像传统(Perl)正则表达式,请使用模式.

指定very magic模式的简单方法是使用以下命令启动正则表达式\v:

" this is a no-op
:s/\v(this is grouped)/\1/
Run Code Online (Sandbox Code Playgroud)

编辑:这个答案有效,但请参阅下面的@ heijp06非常相关的评论(我不知道该&角色有特殊含义).

评论贴在这里:

实际上这个答案是正确的,这实际上有点不同寻常.替换的替换部分中的&替换意味着在这种情况下与模式匹配的那样的结果是正确的.

  • 实际上这个答案是正确的,这实际上有点不同寻常.替换的替换部分中的`&`表示*在这种情况下与模式*匹配的是`&`,因此最终效果是正确的. (5认同)

Ama*_*dan 6

“非捕获”并不意味着您认为的含义。\(...\)和之间的唯一区别\%(...\)是子表达式是否保存到\1\2...仍将匹配项包含在匹配项中。

您想要\@<=:help \@<=):

:s/\(^a*\)\@<=&/\& \&/g
Run Code Online (Sandbox Code Playgroud)


cdo*_*orn 5

通常在搜索和替换中,替换完全替换搜索就足够了。在这种情况下,您的搜索将包括您不想替换的内容。

Vim 有一些有用的模式来定义匹配的开始和结束:\zs\ze。你可以放在\zs搜索的任何地方,vim 只会在开始后匹配。您可以使用两者来表示,找到该特定行并仅替换其中的一部分。

以及解决方案:

:%s:^[^&]*\zs&:& &:c

  • %s: 查看文件中的每一行
  • ^[^&]*:从行首开始,应该有零个或多个 &
  • \zs&:要替换的匹配是单个&
  • & &:将匹配项替换为两个&
  • c:交互地执行每个替换,以防我在正则表达式上表现不佳