Regex 替换vim中出现的第n个单词

Regex 替换vim中出现的第n个单词,regex,vim,sed,substitution,Regex,Vim,Sed,Substitution,我看到了关于查找单词/模式的第n次出现的其他问题,但我找不到如何在vim中替换模式的第n次出现。有一种明显的方法可以对所有事件进行硬编码,如 :s/.*\(word\).*\(word\).*\(word\).*/.*\1.*\2.*newWord.*/g 有更好的方法吗 好吧,如果你做了/gc,那么你可以计算它要求你确认的次数,并在你到达第n:D时继续进行替换你可以通过使用多个搜索来做这件事。:s/pattern/repl/命令中的空模式表示替换最近的搜索结果 :/word//word//

我看到了关于查找单词/模式的第n次出现的其他问题,但我找不到如何在vim中替换模式的第n次出现。有一种明显的方法可以对所有事件进行硬编码,如

:s/.*\(word\).*\(word\).*\(word\).*/.*\1.*\2.*newWord.*/g 

有更好的方法吗

好吧,如果你做了
/gc
,那么你可以计算它要求你确认的次数,并在你到达第n:D时继续进行替换你可以通过使用多个搜索来做这件事。
:s/pattern/repl/
命令中的空模式表示替换最近的搜索结果

:/word//word//word/ s//newWord/
or
:/word//word/ s/word/newWord/
然后,您可以通过执行
@:
,或者甚至执行
10@:
将该命令重复10次,来重复多次

或者,如果我以交互方式执行此操作,我会执行以下操作:

3/word
:s//newWord/r
这将找到从光标开始的第三个单词,然后执行替换。

有关信息

s/\%(\(pattern\).\{-}\)\{41}\zs\1/2/

也可以替换第42次出现。然而,我更喜欢哪一个更简单——即使它不会局限于当前行。

这回答了您的实际问题,但不是您的意图

您询问是否替换一个单词的第n次出现(但似乎表示“在一行内”)。以下是问题的答案,以防有人像我一样发现它=)

对于奇怪的任务(比如需要用“parrot”替换第12次出现的“dog”),我喜欢使用递归录音

首先在@q中清空录音

qqq
现在在q中开始一个新的录音

qq
接下来,手动执行您想要执行的操作(使用上面的示例,将第12次出现的“dog”替换为“parrot”):

删除“dog”并进入insert

diwi
类型鹦鹉

parrot
现在播放您当前的空“@q”录音

@q
这没什么用

最后,停止录制:

q
@q
现在,您在@q中的录制在结尾处自动调用。但是因为它按名称调用录音,所以它不再是空的。因此,请调用录音:

q
@q
它将重放录音,然后在最后,作为最后一步,再次重放自己。它将重复此操作,直到文件结束

TLDR

qq
Q
/狗
nnnnnnnn迪维帕罗
@q
Q
@q
用Replace替换一行中每第n次出现的图案

:%s/\(\zsPATTERN.\{-}\)\{N}/REPLACE/

为了替换vim中一行中第n次出现的模式,除了上面的答案,我只想解释模式匹配,即它实际上是如何工作的,以便于理解

因此,我将讨论
\(.{-}\zsPATTERN\){N}
解决方案

我将使用的示例是替换句子(字符串)中第二次出现的超过1个空格。 根据模式匹配代码->

  • 根据zs文件

    \zs
    -水平滚动文本,将光标定位在起始位置(左侧) 屏幕的侧面)

  • \{-}
    0或更多尽可能少(*)

    在这里。匹配任意字符和{}次。 e、 这里的gab{2,3}c与b出现的地方匹配2次或3次

    在这种情况下,我们还可以使用
    *
    ,它是0或尽可能多。 根据vim非贪婪文档,“{-}”与“*”相同,但使用最短匹配优先算法

  • \{N}
    ->匹配前面原子的N

    /\
    搜索精确的4位数字,与/\

    **忽略这些
    \
    它们是用于精确搜索的,就像搜索fred->
    \
    将只搜索fred而不是alfred

  • \(\)
    组合整个模式

  • 模式这里是您要匹配的模式->
    \s\{1,}
    (\s-space和{1,}如上所述,搜索1个或多个空间)

  • “abc子字符串定义”

    输出->“abc子字符串,定义”


    是的,但是我想在没有确认的情况下替换第n次出现的单词(就像我必须写一个脚本来做一样)。Hrm,这仍然有很多问题,如果第一个单词是我们正在寻找的单词,“3/单词”将使我们进入第四次出现。此外,当我在找到第n个实例后尝试替换时,它仍然替换第一个匹配项。
    3/word
    将查找从光标开始的第三个匹配项。如果要从文件的顶部开始,请使用
    gg
    。请注意,
    3/word
    相当于键入
    /word
    三次,因此它肯定会找到第三个匹配项。-1:如果所有单词都在同一行上,这两个选项对我都不起作用(这是我假设OP的意思)。在这两个例子中,替换仍然发生在行中的第一个单词上。显然在sed中有替换,但在vim
    s///
    中没有替换:@Luc Hermitte:你能告诉我你的答案中“\%”是什么意思吗。它似乎是VIM无法识别的运算符。它类似于
    \(
    ),但它告诉我们不要将括号中匹配的内容绑定到
    \1
    。请参见
    :h/\%(
    ,iirc,你能告诉我
    zs
    {N}
    是正则表达式的语法还是VIM的语法吗?缩放锚是VIM特定的吗(其他语言IDK),请参见Vim中的about
    \zs
    或type
    :h\zs
    以获取有关它的信息,大多数语言中都使用了
    {}
    ,但功能不同,主要用于匹配长度或模式或组匹配的出现时间
    (..){N}
    ,就像我在这里使用的那样。
        :%s/\(.\{-}\zs\s\{1,}\)\{2}/,/
    
    # explanation: first space would be between abc and substring and second 
    # occurence of the pattern would be between substring and def, hence that 
    # will be replaced by the "," as specified in replace command above.