我正在尝试学习如何在vim中使用正则表达式,而我目前正在尝试进行搜索和替换。我有这样的事情:
aaaaaaa&sometext&...
aaaaaaaanothertext
(a
s实际上是该行开头的空格,我不知道如何在这里打印出来。
我希望将&
的第一次出现替换为& &
,并按原样保留其他所有内容。我按照建议here使用\%(...\)
非捕获模式,但仍然捕获了a
模式。我使用:%s/\%(^a*\)&/& &/gc
,我得到了:
aaaaaaaa& aaaaaaaa&sometext&...
aaaaaaaaanothertext
我不明白为什么。我也尝试过替换群组,例如:%s/\%(^a*\)\(&\)/\1 \1/gc
,但后来我得到了:
& &sometext&...
aaaaaaaanothertext
因此,似乎群组处理确实被忽略(因为第一组在搜索模式上是&
),但仍然在搜索模式上捕获。
所以,长话短说,我必须使用替换命令:
aaaaaaa&sometext&...
为:
aaaaaaa& &sometext&...
答案 0 :(得分:6)
我想将
&
的第一次出现替换为& &
,并保留 其他一切都是
使用替换命令:
:s/&/& &/
另一个提示:默认情况下,Vim将(
视为文字字符,而不是组的开头。
如果您希望正则表达式更像传统(Perl)正则表达式,请使用very magic
模式。
指定very magic
模式的简便方法是使用\v
启动正则表达式:
" this is a no-op
:s/\v(this is grouped)/\1/
编辑:这个答案有效,但请参阅@ heijp06以下非常相关的评论(我不知道&
字符有特殊意义。)
评论粘贴在这里:
为什么这个答案是正确的,实际上有点不重要。一个&在 替换的替换部分意味着匹配的东西 在这种情况下的模式是&所以最终效果是正确的。
答案 1 :(得分:4)
“非捕获”并不代表您认为的含义。 \(...\)
和\%(...\)
之间的唯一区别在于子表达式是否已保存到\1
,\2
...它仍将包含匹配中匹配的内容。< / p>
您想要\@<=
(:help \@<=
):
:s/\(^a*\)\@<=&/\& \&/g
答案 2 :(得分:0)
通常在搜索和替换中,替换项完全替换搜索就足够了。在这种情况下,您的搜索将包括您不想替换的内容。
Vim具有有用的模式来定义比赛的开始和结束:\zs
和\ze
。您可以将\zs
放在搜索中的任何位置,vim仅在开始之后匹配。您可以使用两者来说,找到此特定行,而只替换其中一部分。
解决方法:
:%s:^[^&]*\zs&:& &:c
%s
:查看文件中的每一行^[^&]*
:从该行的开头开始,应该为零或多个 not &
\zs&
:要替换的匹配项是单个&
& &
:将匹配项替换为两个&
c
:在我对正则表达式感到厌烦的情况下,以交互方式执行每个替换