vi ::如何只替换一行中的第二次出现?

时间:2014-04-01 02:08:45

标签: regex vi options

:s / u / X / 2 - 这会将当前和下一行的第一个u替换为X ...

或用X ????替换一行中的第二个字符IDK。

或者它的其他东西:s?

我怀疑我必须使用某种类型的分组(\ 2?)但是我不知道要写那个。

我听说sed中的sed和:s选项是相似的,在sed的帮助页面上我发现:

3.1.3. Substitution switches:

Standard versions of sed support 4 main flags or switches which may be added to
the end of an "s///" command. They are:

   N      - Replace the Nth match of the pattern on the LHS, where
            N is an integer between 1 and 512. If N is omitted,
            the default is to replace the first match only.
   g      - Global replace of all matches to the pattern.
   p      - Print the results to stdout, even if -n switch is used.
   w file - Write the pattern space to 'file' if a replacement was
            done. If the file already exists when the script is
            executed, it is overwritten. During script execution,
            w appends to the file for each match.

http://sed.sourceforge.net/sedfaq3.html#s3.1.3

所以::r! sed 's/u/X/2'会起作用,虽然我认为有一种特殊的方法可以做到这一点吗?

IDK如果相关,但我使用的是tcsh shell。

:versionVersion 1.79 (10/23/96) The CSRG, University of California, Berkeley.

3 个答案:

答案 0 :(得分:4)

这很脆弱,但可能足以做你想做的事。这个带有正则表达式的开关命令:

:%s/first\(.\{-}\)first/first\1second/g

将此转换为:

first and first then first again
first and first then first again
first and first then first again
first and first then first again

到此:

first and second then first again
first and second then first again
first and second then first again
first and second then first again

正则表达式查找第一个“第一个”,然后使用模式.\{-}匹配任何字符,这是.*的非贪婪版本(类型:help non贪婪在vim中获取更多信息。)这个非贪婪的匹配之后是第二个“第一个”。

第一个和第二个“第一个”之间的字符是通过用括号括起.\{-}来捕获的,在\(.\{-}\)中有转义结果,然后使用{{1}取消引用该捕获的组替换中的(1表示第一个被捕获的组)。

答案 1 :(得分:1)

为了替换第二次出现在一行上,您可以说:

:call feedkeys('nyq') | s/u/X/gc

要在一系列行或整个文件中调用它,请在函数中使用它:

:function Mysub()
:  call feedkeys('nyq') | s/u/X/gc
:endfunction

例如,以下内容将替换文件中每一行u的{​​{1}}的第二次出现:

X

答案 2 :(得分:0)

这是一个愚蠢但更容易理解的方法:首先找到文件中不存在的字符串-为了进行论证,假定它是zzz。然后简单地:

:%s/first/zzz
:%s/first/second
:%s/zzz/first