Vim:在多行中插入相同的字符


306

有时我想跨多行编辑特定的可视文本块。

例如,我将输入如下文本:

name
comment
phone
email

并使其看起来像这样

vendor_name
vendor_comment
vendor_phone
vendor_email

目前我现在要做的方式是...

  1. 按下V然后选择j四次,选择一个块的所有4行。
  2. 缩进>
  3. 回上一个字母h
  4. 使用进入阻止视觉模式Ctrlv
  5. 按下四下选择四行j。此时,您已经选择了一个4x1的可视空白块(四行一列)。
  6. C。请注意,这几乎缩进了一列。
  7. 输入" vendor_"不含引号的a。请注意,我们不得不退还多余的空间。
  8. Esc。这是我Esc用来退出插入模式的极少数情况之一。Ctrlc只会编辑第一行。
  9. 重复步骤1。
  10. 缩进另一种方式<

我不需要缩进单词之前是否至少有一列空格。如果不必使用清除可视块,则不需要空格c

但是,如果我必须清除,那么有没有一种方法可以做上面的事情而又不用缩进来创建所需的空格?

另外,为什么一次编辑多行只能通过退出带有Escover 的插入模式来工作Ctrlc


这是一个更复杂的示例:

name    = models.CharField( max_length = 135 )
comment = models.TextField( blank = True )
phone   = models.CharField( max_length = 135, blank = True )
email   = models.EmailField( blank = True )

name    = models.whatever.CharField( max_length = 135 )
comment = models.whatever.TextField( blank = True )
phone   = models.whatever.CharField( max_length = 135, blank = True )
email   = models.whatever.EmailField( blank = True )

在此示例中,我将在上执行垂直可视块.,然后在插入模式(即type)中重新将其重新插入.whatever.。希望现在您可以看到此方法的缺点。我仅限于选择一列在垂直位置都相同的文本。


9
更好的方法:“:%s / ^ / vendor_ /”
Paul Tomblin,

1
感谢您的回复。如果我只想在每行后面附加一个单词,那是可行的。但是我使用的方法可以在任何位置完成。让我再添加一个示例,其中包含一个更复杂的示例。
hobbes3 2012年

3
然后突出显示要与转变-V变化的线条,然后键入适当的搜索和替换命令-在第二个例子中,:s/models\./\0whatever./
保罗汤布林

实现上述目标的方法很多。为了完全回答问题的所有部分,然后是第1部分),无论是正则表达式还是可视模式,我编辑esc都可以很好地如答案中所提供的那样工作(我更喜欢GVIM中的可视选择)。对于第2部分,宏可能是Brian Neal提供的最简单的方法。我所知道的关于所有此类“如何做”的最佳资源是Drew Neil的《实用Vim》。每当您忘记公式时,它都是出色的快速阅读和轻量参考。希望此建议对某人有帮助,对于许多vim用户来说,这是值得的。
arcseldon 2013年

@Paul:如果您要计算击键次数,则可以替换\0&
icktoofay 2014年

Answers:


912
  1. 将光标移到nname
  2. 进入可视块模式(Ctrlv)。
  3. j三次(或3j)。
  4. I(大写i)。
  5. 输入vendor_。注意:它将仅更新第一行中的屏幕-直到Esc按下(6.),此时所有行都将被更新。
  6. Esc

微型截屏演示方法

I必须使用大写而不是小写i,因为小写i被解释为文本对象的开始,它本身非常有用,例如,用于在标记块(it)中进行选择:

微型截屏视频,显示“ it”文本对象的有用性


12
我无法在Windows中使用它(因为CTRL + V已映射为剪贴板粘贴)。但是对于Windows版本,Vim还将此映射到Ctrl + Q。
Arnestig 2014年

2
@Ven:Vim在这段时间实际上并不忙-它只是在等待您按另一个键,最终超时。为您进行两个实验:首先,尝试按Escape键,然后立即按另一个键,例如j^L。您应该看到Vim毕竟不忙。它只是在等待。其次,尝试更改'timeout'为一个较低的值,例如80(而不是默认值1000),并观察其超时更快。
icktoofay 2014年

1
@icktoofay看来您要设置的变量timeoutlen不是timeout
jez

4
@ANjaNA:如果要插入的位置全部在同一列中(例如,如果数字都具有相同的长度),则可以使用相同的技术,但要按下A而不是I,这将在所选块之后而不是之前插入。但是,如果您的线长不同,那将行不通。我喜欢为此使用匹配每行结尾的替换,例如选择一些行并使用:s/$/inserted/
icktoofay 2015年

3
我必须按esc键后才能按向下箭头才能使其正常工作
GeoSword

69

另一种方法是将.dot)命令与结合使用I

  1. 将光标移到要开始的位置
  2. I
  3. 输入您想要的前缀(例如vendor_
  4. esc
  5. 按下j以向下一行
  6. 键入.以重复上一次编辑,然后再次自动插入前缀
  7. j和之间快速切换.

我发现,对于少量添加,此技术通常比可视块模式更快,并且具有附加的好处,即如果您不需要在范围内的每一行上插入文本,则可以通过按extra轻松地跳过它们j。 。

注意,对于大量连续的添加,块方法或宏可能会更好。


很高兴看到另一种方法。
伊本·赛义德2014年

我只喜欢这几行。执行IMO容易得多。
丹·贝查德

输入所需的前缀后,是否不需要按Escape键?
iamnotsam 2014年

41
  1. 使用选择要修改的行CtrlV
  2. 按:

    • I:在所选内容之前插入。
    • A:在选择的内容之后附加。
    • c:替换所选内容。
  3. 输入新文本。

  4. Esc将更改应用到所有选定的行。

4
优秀的!我只是强调Esc像我这样的VIM新手的最后一步-我花了一段时间才弄清楚这些变化“后来”得到了传播!
Bugs Bunny,

1
很好,也不知道“ A”和“ C”选项。
hobbes3

为什么这不起作用v?我可以用来Ctrl+V --> A做,但是v选择文本不起作用- A只能追加到该行。他们不是都选择吗?同样,非常奇怪- A如果我将可视块扩展到该行的末尾,则仅追加到该行的末尾;否则,它会附加在每行可视块结束的位置。好像无法识别a和之间的区别A
亚历克斯G

1
我需要使用c而不是C,但是效果很好。谢谢
Tarol

29

我将使用宏来记录我的操作,然后重复执行。

  1. 将光标放在中的第一个字母上 name
  2. 击中 qq开始录制到q缓冲区。
  3. 点击i进入插入模式,键入vector_,然后点击Esc离开插入模式。
  4. 现在打 0返回到该行的开头。
  5. 现在打 j
  6. 现在打 q再次点击以停止录制。

您现在有了一个不错的宏。

键入3@q执行宏三遍,以完成其余各行。


“ q”是否特殊(对于“快速宏”而言?)?
Peter Mortensen

如何使宏保持不变(跨多个会话工作)?
Peter Mortensen

@PeterMortensen Vim具有称为会话的功能,该功能将持久化您可以查看的缓冲区(以及许多其他内容)。
Brian Neal

27
:%s/^/vendor_/

还是我错过了什么?


您缺少这样一个事实,它很可能是文件中包含很多其他vender_不需要前缀的行的子文本。
丹·贝查德

9
@dan如果只需要一个文本,则可以将搜索限制为一组行号,例如1,4s/^/vendor_/
Brad Koch

1
@BradKoch有趣。我不知道行号的限制,为此。
丹·贝查德

8
这很有趣,但是更实用的方法是在视觉上使用select V和type 阻止选择:。它将在ed表达式之前加上前缀:'<,'>,使ed仅适用于:'<,'>s/^/vendor_/
Dolanor '16

12

2016年1月更新

虽然可接受的答案是一个很好的解决方案,但实际上这是击键次数少一点,并且伸缩性更好的方法-原则上基于可接受的答案。

  1. 将光标移到nname
  2. 进入可视块模式(ctrlv)。
  3. 3j
  4. I
  5. 输入vendor_
  6. esc

视觉插图

请注意,其击键次数少于所提供的可接受答案(比较步骤3)。我们只计算要执行的j个动作的数量。

如果您启用了行号(如上所示),并且知道您要移至的行号,则可以将步骤3更改为#G,其中#是所需的行号。

在上面的示例中,该值为4G。但是,当只处理几个行号时,显式计数会很好地工作。


7

我想在只有vi(没有nano)的服务器上的一些配置文件中注释掉很多行,因此可视方法也很麻烦。这就是我的方法。

  1. 打开文件 vi file
  2. 显示行号:set number!:set number
  3. 然后使用行号将行首替换为“#”,怎么办?

:35,77s/^/#/

注意:这些数字包含在内,从35到77的行(都包括在内)将被修改。

要取消注释/撤消该注释,只需使用 :35,77s/^#//

如果要在每一行代码后添加文本词作为注释,则还可以使用:

:35,77s/$/#test/ (适用于Python之类的语言)

:35,77s/;$/;\/\/test/ (用于Java之类的语言)

学分/参考:

  1. /unix/84929/uncommenting-multiple-lines-of-code-specified-by-line-numbers-using-vi-or-vim

  2. /unix/120615/how-to-comment-multiple-lines-at-once


这对我来说是完美的解决方案,因为我经常只使用vim-tiny。
JSON C11,19年

7

您可能还有一个用例,其中您要删除一段文本并替换它。

像这样

Hello World

Hello World

Hello Cool

Hello Cool

您可以只在两行中用视觉块选择“世界”。

c输入更改类型-现在您将处于插入模式。

插入所需的内容,然后按Escape键。

两者都会垂直反射。它与“ I”的工作方式相同,只是它用新文本替换了块而不是插入了新文本。


6

假设您有以下文件:

something

name
comment
phone
email

something else
and more ...

您希望在“名称”,“评论”,“电话”和“电子邮件”之前添加“ vendor_”,无论它们在文件中的位置如何

:%s/\<\(name\|comment\|phone\|email\)\>/vendor_\1/gc

c标志将提示您进行确认。如果您不希望出现提示,可以将其删除。


5

可以更灵活的替代方法:

示例:在行首输入文本XYZ

:%norm IXYZ

这里发生了什么事?

  • % ==每行执行
  • norm ==在普通模式下执行以下键
  • I ==在行首插入
  • XYZ ==您要输入的文字

然后点击Enter,然后执行。

针对您的要求:

:%norm Ivendor_

您还可以选择一个特定范围:

:2,4norm Ivendor_

或在选定的可视范围内执行:

:'<,'>norm Ivendor_

1
是否可以在插入模式(规范Iabc <ESC>)中发送诸如<Esc>之类的键序列,以执行更多有趣的操作?
batbrat

1
@batbrat我刚刚想通了!您可以单击ctrl-v ctrl-[以插入“转义的Esc”,出于正常命令的目的,这会将您拉回到“正常模式”。我刚刚使用进行了测试'<,'>norm Iaa^[ysiw"^[转义的Esc 在哪里。
奥布里·拉维尼

4
Use Ctrl+V to enter visual block mode
Move Up/Down to select the columns of text in the lines you want to comment.
Then hit Shift+i and type the text you want to insert.
Then hit Esc, wait 1 second and the inserted text will appear on every line

这种方法是否适用于所有版本的vim或需要任何vim插件?我问的原因是b / c有时可以在某些机器上使用,但有时不能。我不知道区别。Windows上git附带的vim-我无法正常运行。在某些ubuntu和centos linux计算机上,我无法正常运行。我在少数情况下取得了成功,但我无法复制成功。这是一个谜。我按下ESC后似乎什么也没发生。
davidj411 '17

奇怪的是,它现在对我有用。一切都没有改变,也许只是星星:)在寻找解决方案时,我确实在此页面上找到了一些东西,尽管其中提到了要在vim中寻找的东西 vim.wikia.com/wiki/Inserting_text_in_multiple_lines 在Vim中,检查是否有通过输入:version命令,逐块运算符功能(I,A等)。输出应包括+ visualextra。
davidj411

我的意思是一般添加评论,而不是您的答案。这些答案大多数都说相同的话,只是用不同的词。我的提供的东西有所不同,并包含一个链接。
davidj411

2
  1. Ctrl + v进入可视块模式
  2. 使用上下箭头选择线
  3. 输入小写字母3i(按小写字母 I 3次)
  4. I(按大写字母I。这将使您进入插入模式。)
  5. 写下您要添加的文字
  6. Esc
  7. 按下向下箭头
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.