:s/pattern/replacement在第一个匹配项上运行,
:s/pattern/replacement/g在所有匹配项上运行。

如何仅在最后一个匹配项上运行?

#1 楼

我会使用\zs

:%s/.*\zspattern/replacement/


一点解释:



.代表任何单个字符

*表示贪婪匹配(尽可能多)

在Vim中,您可以使用零宽度锚点\zs\ze定义搜索模式的开始和结束,希望匹配。模式中\zs之前和\ze之后的任何内容都不会受到替换的影响。

为了易于理解,我想使用Wikia搜索和替换中的以下示例:


通过使用\zs\ze设置
模式的开始和结束来保存键入。例如,代替:

:s/Copyright 2007 All Rights Reserved/Copyright 2008 All Rights Reserved/ 


使用:

:s/Copyright \zs2007\ze All Rights Reserved/2008/



有关更多信息,看看


:h \zs
:h pattern-overview


评论


您能否提供\ zs答案的基本描述?

–EvergreenTree
2015年10月13日在17:59



值得注意的是,此功能起作用的原因是因为*是贪婪的。

–通配符
16 Mar 25 '16 at 0:24

#2 楼

您可以通过将所有\(.*\)分组,但将最近一次出现的pattern分组来搜索最后一个匹配项。然后与捕获的组退出,并添加replacement

:%s/\(.*\)pattern/replacement/


评论


(这比@ryuichiro的\ zs解决方案逊色,因为您的\ 1方法在功能上是等效的,但是更冗长。(另一方面,对于某些方法,可能更容易记住,尤其是当它们习惯于其他正则表达式时)。 ))

–亚伦·托马
16/12/30在1:44



#3 楼

为了完整起见,我认为我会发布一个替代方案。 Vim有多个项目,其中一些类似于更标准的正则表达式环顾断言(负/正向超前/向后看)。 https://stackoverflow.com/questions/2973436/regex-lookahead-lookbehind-and-atomic-groups

在这种情况下,我们想要一个负的前瞻\@!,这意味着我们想断言原子模式之前不会发生在项目之前的内容。在这种情况下,原子本身就是模式之前的其他任何形式:

:%s/pattern\(.*pattern\)\@!/replacement/


括号内的部分为零宽度,不包含在匹配项中,因此不会被替换

:h \@!以获得更多信息,或:h pattern-multi-items包含其他环视变化的整个部分。