如何在Vim中将文本插入到多行的中间?

92

假设我有十行文本,我想在其中某个单词前面添加文本?这个单词不一定在行的开头。

来自:

sdfsd   foo sdfsd
sfsd    foo fsdf
sdfsdf  foo  sdfsdf
转至:
sdfsd   bar(foo sdfsd
sfsd    bar(foo fsdf
sdfsdf  bar(foo  sdfsdf

不仅可以在 foo 前添加 bar( ,而且还可以将 foo 包裹在 bar(foo) 中,这也是可能的吗?

我还想快速地将多行添加 // 注释(C风格注释)。

我使用 Vim/GVim 7.2。


1
C风格的注释是/* */,BCPL风格的注释是//。 - William Pursell
相关:在Vim SE上如何注释掉选定的一组行? - kenorb
7个回答

171

进入第一个 foo,按下 Ctrl-v 进入可视块模式,并按下向下箭头直到所有带有 foo 的行都被标记。 然后按下 Shift-i 在块的开头插入。 当您完成并按下 Esc 时,插入的字符将添加到标记块左侧的每一行。

要在结尾处插入,请再次按下 Ctrl-v,上下移动以标记所有受影响的行,然后按下 End$ 扩展选择,直到行的结尾。 现在您可以按下 Shift-a 在所有行的末尾追加,就像之前使用 Shift-i 一样。

可视化选择也可以使用普通移动命令完成。 因此,要在C中注释整个块,您可以移动到开放括号并键入 Ctrl-v % Shift-i // Esc


5
补充一点:如果在Windows上使用Vim时,按Ctrl-V不能启动可视块模式,则应改用Ctrl-Q。 - Paul
3
一种变体的答案是使用shift+V标记可视块,然后在ex模式下更改该块: :'<,'>s/^/前缀文本/ :'<,'>s/$/后缀文本/ 注意,当您按“:”时,vim会自动打印“'<,'>”。 - dimba
9
值得注意的是,在Linux系统中,要使前缀应用于所有行,需要在插入模式下退出,并且需要使用大写字母"I"进入插入模式,即从可视模式切换到插入模式,方法是Shift+I,输入前缀,然后按两次Escape键。 - Joshua Enfield
6
在 PuTTY 上无法使用。按下 i 没有任何反应。按下 shift+i 会使选择消失,但我可以插入文本(只能在光标所在的当前位置插入)。 - Jürgen Paul
1
我认为有些人可能会因按下Escape键后稍有延迟而得到错误印象,等一会儿,更改将会生效,只需要按下一次Escape键,就像他的回答所说的那样(完全一样)。并且新用户不要忘记,如果您使用#来注释shell脚本,那么#也是高亮键,当您进行此操作时不要让其混淆。 - osirisgothra
显示剩余5条评论

44
回答你的第一个问题,以下是内容。
:%s/foo/bar(&)/g

将查找foo,并使用bar()包围匹配的模式。 /g将在一行中多次执行此操作。

由于您只是匹配foo,因此可以执行简单的:s/foo/bar(foo)/g。上述方法有效,但如果您决定匹配正则表达式而不是简单的单词(例如f[a-z][a-z]),则上述方法就无法胜任。上面的'&'代表了您匹配到的内容。


我本来有一个很长的答案,里面包含宏。但这样简单多了 :-) - Brian Ramsay
你如何对多行进行替换?一个实际的情况是当你有一段由相似行组成的代码块需要进行这种替换。 - Sasha
有趣的是,:%s/foo/bar(&)/gc 并不会确认 -- 'c' 没有效果.. 唉 - Sasha
@ Sasha - 所以上述方法适用于你的多行情况。 - Brian Agnew
1
:s 之间的文本决定了它所操作的行。什么都不写表示只操作当前行。1,30 表示从第一行到第三十行(包括第一行和第三十行)。'<,'> 表示当前可视化选择中的所有行。 - rampion
显示剩余3条评论

18

为了给一组行添加前缀,我使用两种不同的方法:

其中一种方法是块选择(由sth提到)。通常,您可以使用ctrl-V和光标移动来选择一个矩形区域。一旦您突出显示了一个矩形,按shift-I将在矩形左侧插入字符,或按shift-A将在矩形右侧附加字符。因此,您可以使用此技术创建一个包括要添加前缀的行的最左列的矩形,按shift-I,键入前缀,然后按Esc。

另一种方法是使用替换方法(由Brian Agnew提到)。 Brian的替换将影响整个文件(命令中的%表示“所有行”)。要影响几行,最简单的方法是在第一/最后一行上按下shift-V(启用可视化行模式),然后移动到最后/第一行。然后输入:

:s/^/YOUR PREFIX/

^是正则表达式中的符号(在这种情况下是行首)。在可视化行模式下键入此符号,您将看到自动在s之前插入“<,”和“>”。这意味着替换的范围将是可视选择。

额外提示:如果您的前缀包含斜杠,则可以使用反斜杠进行转义,或者您可以使用其他标点符号作为命令中的分隔符。例如,要添加C++行注释,我通常会写:

:s:^:// :

如果要添加后缀,替换方法通常比较容易,除非所有行的长度都完全相同。只需使用$代替^作为模式,您的字符串就会被附加而不是预先添加。

如果您想同时添加前缀和后缀,可以这样做:

:s/.*/PREFIX & SUFFIX/

.* 匹配整行文本。替换中的 & 把匹配到的文本(整行)放回去,但现在它将附加你的前缀和后缀。

顺便说一下:当注释代码时,您可能希望稍后取消注释。您可以使用可视块 (ctrl-V) 选择斜线然后按 d 键删除它们,或者您可以使用替换(可能需要使用可视行选择,使用 shift-V 创建)以删除前导斜杠,如下所示:

:s:// ::

6

:normal救命啊!

:%norm Wibar(

:%norm WEa)

:norm(al)会重新执行命令,就好像你自己输入一样:

W - 跳到下一个单词

i - 开始插入模式

bar( - 输入 'bar('

或者在一行中完成:

:%norm Wibar(ctrlvESCEa)

如果你在运行Windows,则将ctrlv替换为ctrlq


3

另一种可能性(在您的测试案例中可能不太有用,但在其他情况下非常方便)是使用标记来隔离要更改的区域。

  • 将光标放置在顶部行的任意位置,然后按'a
  • 将光标放置在最后一行的任意位置,然后按'b
  • 输入命令:'a,'b s/foo/bar(&)/

如果所有内容都在屏幕上可见,我通常喜欢使用可视块模式;如果起始点和终止点相距很远,则我通常更喜欢使用标记。


应该使用 m 而不是 ' 来设置新的标记。' 用于跳转到现有标记所在的行。``` 则会跳转到该标记所在的行和列。 - tiktak

1
另一个简单的正则表达式是:

%s/^/<text you want to prepend>/

0

对于C风格的注释,请使用Brian提供的正则表达式答案,并匹配行尾$,然后进行插入。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接