我正在尝试学习如何使用vim的正则表达式,我正在尝试进行搜索和替换.我有这样的事情:
aaaaaaa&sometext&...
aaaaaaaanothertext
Run Code Online (Sandbox Code Playgroud)
(a
s实际上是行开头的空格,我不知道如何在这里打印)
我想替换第一次出现的&
有& &
,并保持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)
?
我想替换第一次出现
&
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非常相关的评论(我不知道该&
角色有特殊含义).
评论贴在这里:
实际上这个答案是正确的,这实际上有点不同寻常.替换的替换部分中的&替换意味着在这种情况下与模式匹配的那样的结果是正确的.
“非捕获”并不意味着您认为的含义。\(...\)
和之间的唯一区别\%(...\)
是子表达式是否保存到\1
,\2
...仍将匹配项包含在匹配项中。
您想要\@<=
(:help \@<=
):
:s/\(^a*\)\@<=&/\& \&/g
Run Code Online (Sandbox Code Playgroud)
通常在搜索和替换中,替换完全替换搜索就足够了。在这种情况下,您的搜索将包括您不想替换的内容。
Vim 有一些有用的模式来定义匹配的开始和结束:\zs
和\ze
。你可以放在\zs
搜索的任何地方,vim 只会在开始后匹配。您可以使用两者来表示,找到该特定行并仅替换其中的一部分。
以及解决方案:
:%s:^[^&]*\zs&:& &:c
%s
: 查看文件中的每一行^[^&]*
:从行首开始,应该有零个或多个不 &
\zs&
:要替换的匹配是单个&
& &
:将匹配项替换为两个&
c
:交互地执行每个替换,以防我在正则表达式上表现不佳