替换 vim 中第 n 次出现的单词

发布于 2024-09-06 05:21:10 字数 196 浏览 5 评论 0原文

我看到其他问题涉及查找单词/模式的第 n 次出现,但我找不到如何在 vim 中实际替换模式的第 n 次出现。有一种明显的方法可以对所有出现的情况进行硬编码,例如

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

是否有更好的方法来做到这一点?

I saw other questions dealing with the finding the n-th occurrence of a word/pattern, but I couldn't find how you would actually substitute the n-th occurrence of a pattern in vim. There's the obvious way of hard coding all the occurrences like

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

Is there a better way of doing this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

迟到的我 2024-09-13 05:21:10

作为信息,

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

也可以替换第 42 次出现。但是,我更喜欢 给出的解决方案John Kugelman 更简单——即使它不会将自己限制在当前行。

For information,

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

also works to replace 42th occurrence. However, I prefer the solution given by John Kugelman which is more simple -- even if it will not limit itself to the current line.

素食主义者 2024-09-13 05:21:10

您可以通过使用多个搜索来更简单地完成此操作。 :s/pattern/repl/ 命令中的空模式表示替换最新的搜索结果。

:/word//word//word/ s//newWord/
or
:/word//word/ s/word/newWord/

然后,您可以通过执行 @: 多次重复此操作,甚至可以使用 10@: 重复该命令 10 次。

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

3/word
:s//newWord/r

这将找到从光标开始的第三次出现的单词,然后执行替换。

You can do this a little more simply by using multiple searches. The empty pattern in the :s/pattern/repl/ command means replace the most recent search result.

:/word//word//word/ s//newWord/
or
:/word//word/ s/word/newWord/

You could then repeat this multiple times by doing @:, or even 10@: to repeat the command 10 more times.

Alternatively, if I were doing this interactively I would do something like:

3/word
:s//newWord/r

That would find the third occurrence of word starting at the cursor and then perform a substitution.

吹泡泡o 2024-09-13 05:21:10

将一行中每第 N 次出现的 PATTERN 替换为 REPLACE。

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

Replace each Nth occurrence of PATTERN in a line with REPLACE.

:%s/\(\zsPATTERN.\{-}\)\{N}/REPLACE/
猥琐帝 2024-09-13 05:21:10

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

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

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

  1. 根据 zs 文档,

    \zs - 水平滚动文本以将光标定位在开头(左侧)

  2. .\{-} 0 个或更多,尽可能少 (*)

    这里。匹配任意字符和 {} 次数。
    例如,这里的 ab{2,3}c 它将匹配 b 出现 2 次或 3 次的情况。

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

  3. <代码>\{N} ->匹配前一个原子的 n 个

    /\<\d\{4}\> 精确搜索 4 位数字,与 /\<\d\d\d\d>

    **忽略这​​些\<\>,它们用于精确搜索,例如搜索fred -> \ 只会搜索 fred 而不会搜索 alfred。

  4. \( \) 组合整个模式。

  5. PATTERN 这是您要匹配的模式 -> \s\{1,} (\s - 空格和 {1,},如上所述,搜索 1 个或多个空格)

“abc 子串定义”

<前><代码> :%s/\(.\{-}\zs\s\{1,}\)\{2}/,/

输出-> “abc 子串,def”

# 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. 

To replace the nth occurrence of PATTERN in a line in vim, in addtion to the above answer I just wanted to explain the pattern matching i.e how it is actually working for easy understanding.

So I will be discussing the \(.\{-}\zsPATTERN\)\{N} solution,

The example I will be using is replacing the second occurrence of more than 1 space in a sentence(string).
According to the pattern match code->

  1. According to the zs doc,

    \zs - Scroll the text horizontally to position the cursor at the start (left
    side) of the screen.

  2. .\{-} 0 or more as few as possible (*)

    Here . is matching any character and {} the number of times.
    e.g ab{2,3}c here it will match where b comes either 2 or 3 times.

    In this case, we can also use .* which is 0 or many as many possible.
    According to vim non-greedy docs, "{-}" is the same as "*" but uses the shortest match first algorithm.

  3. \{N} -> Matches n of the preceding atom

    /\<\d\{4}\> search for exactly 4 digits, same as /\<\d\d\d\d>

    **ignore these \<\> they are for exact searching, like search for fred -> \<fred\> will only search fred not alfred.

  4. \( \) combining the whole pattern.

  5. PATTERN here is your pattern you are matching -> \s\{1,} (\s - space and {1,} as explained just above, search for 1 or more space)

"abc subtring def"

    :%s/\(.\{-}\zs\s\{1,}\)\{2}/,/

OUTPUT -> "abc subtring,def"

# 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. 
韶华倾负 2024-09-13 05:21:10

这回答了您的实际问题,但没有回答您的意图。

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

对于奇怪的任务(例如需要将每 12 次出现的“狗”替换为“鹦鹉​​”),我喜欢使用递归录音。

首先清空 @q 中的录音

qqq

现在在 q 中开始新的录音

qq

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

/dog
nnnnnnnnnnn

删除“dog”并获取插入

diwi

类型 parrot

parrot

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

@q

该录音不执行任何操作。

最后,停止录音:

q

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

@q

它将重播录音,然后在最后,作为最后一步,再次重播。它将重复此操作直到文件末尾。

太长了;

qq
q
/dog
nnnnnnnnnnndiwiparrot<esc>
@q
q
@q

This answers your actual question, but not your intent.

You asked about replacing the nth occurrence of a word (but seemed to mean "within a line"). Here's an answer for the question as asked, in case someone finds it like I did =)

For weird tasks (like needing to replace every 12th occurrence of "dog" with "parrot"), I like to use recursive recordings.

First blank the recording in @q

qqq

Now start a new recording in q

qq

Next, manually do the thing you want to do (using the example above, replace the 12th occurrence of "dog" with "parrot"):

/dog
nnnnnnnnnnn

delete "dog" and get into insert

diwi

type parrot

parrot

Now play your currently empty "@q" recording

@q

which does nothing.

Finally, stop recording:

q

Now your recording in @q calls itself at the end. But because it calls the recording by name, it won't be empty anymore. So, call the recording:

@q

It will replay the recording, then at the end, as the last step, replay itself again. It will repeat this until the end of the file.

TLDR;

qq
q
/dog
nnnnnnnnnnndiwiparrot<esc>
@q
q
@q
攒一口袋星星 2024-09-13 05:21:10

好吧,如果你执行 /gc 那么你可以计算它要求你确认的次数,并在到达第 n 次时继续替换:D

Well, if you do /gc then you can count the number of times it asks you for confirmation, and go ahead with the replacement when you get to the nth :D

捂风挽笑 2024-09-13 05:21:10

两个正则表达式按照最初的预期完成工作:

每行 %s/^\(.\{-}word\)\{3}\zs/* ,或

%s/\ (word\(\_.\{-}word\)\{15}\)\zs\(\_.*\)/*\3 表示整个文档,后跟:

%s /word\*/newword

请注意,可以更改 \{3}\{15} 以获得所需的出现次数,以及匹配

Two regex do the job as initially intended:

%s/^\(.\{-}word\)\{3}\zs/* for each line, OR

%s/\(word\(\_.\{-}word\)\{15}\)\zs\(\_.*\)/*\3 for whole document, followed by:

%s/word\*/newword

Note that can change \{3} and \{15} for desired occurrence number, as well as the match word.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文