替换 vim 中第 n 次出现的单词
我看到其他问题涉及查找单词/模式的第 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
作为信息,
也可以替换第 42 次出现。但是,我更喜欢 给出的解决方案John Kugelman 更简单——即使它不会将自己限制在当前行。
For information,
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.
您可以通过使用多个搜索来更简单地完成此操作。
:s/pattern/repl/
命令中的空模式表示替换最新的搜索结果。然后,您可以通过执行
@:
多次重复此操作,甚至可以使用10@:
重复该命令 10 次。或者,如果我以交互方式执行此操作,我会执行以下操作:
这将找到从光标开始的第三次出现的单词,然后执行替换。
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.You could then repeat this multiple times by doing
@:
, or even10@:
to repeat the command 10 more times.Alternatively, if I were doing this interactively I would do something like:
That would find the third occurrence of word starting at the cursor and then perform a substitution.
将一行中每第 N 次出现的 PATTERN 替换为 REPLACE。
Replace each Nth occurrence of PATTERN in a line with REPLACE.
为了替换 vim 中一行中第 n 次出现的 PATTERN,除了上面的答案之外,我只是想解释一下模式匹配,即它实际上是如何工作的,以便于理解。
我将使用的示例是替换 中第二次出现的超过 1 个空格一个句子(字符串)。
根据模式匹配代码->
根据 zs 文档,
\zs
- 水平滚动文本以将光标定位在开头(左侧))
.\{-}
0 个或更多,尽可能少 (*)这里。匹配任意字符和 {} 次数。
例如,这里的 ab{2,3}c 它将匹配 b 出现 2 次或 3 次的情况。
在这种情况下,我们还可以使用
.*
,它是0或尽可能多的。根据 vim 非贪婪文档,“{-}”与“*”相同,但使用最短匹配优先算法。
<代码>\{N} ->匹配前一个原子的 n 个
/\<\d\{4}\>
精确搜索 4 位数字,与 /\<\d\d\d\d>**忽略这些
\<\>
,它们用于精确搜索,例如搜索fred ->\
只会搜索 fred 而不会搜索 alfred。\( \)
组合整个模式。PATTERN 这是您要匹配的模式 ->
\s\{1,}
(\s - 空格和 {1,},如上所述,搜索 1 个或多个空格)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.
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->
According to the zs doc,
\zs
- Scroll the text horizontally to position the cursor at the start (leftside) of the screen.
.\{-}
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.
\{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.\( \)
combining the whole pattern.PATTERN here is your pattern you are matching ->
\s\{1,}
(\s - space and {1,} as explained just above, search for 1 or more space)这回答了您的实际问题,但没有回答您的意图。
您询问是否替换第 n 次出现的单词(但似乎意味着“在一行内”)。这是所问问题的答案,以防有人像我一样发现它 =)
对于奇怪的任务(例如需要将每 12 次出现的“狗”替换为“鹦鹉”),我喜欢使用递归录音。
首先清空 @q 中的录音
现在在 q 中开始新的录音
接下来,手动执行您想做的事情(使用上面的示例,将第 12 次出现的“dog”替换为“parrot”):
删除“dog”并获取插入
类型 parrot
现在播放当前空的“@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
Now start a new recording in q
Next, manually do the thing you want to do (using the example above, replace the 12th occurrence of "dog" with "parrot"):
delete "dog" and get into insert
type parrot
Now play your currently empty "@q" recording
which does nothing.
Finally, stop recording:
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:
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;
好吧,如果你执行
/gc
那么你可以计算它要求你确认的次数,并在到达第 n 次时继续替换:DWell, 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两个正则表达式按照最初的预期完成工作:
每行
%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 matchword
.