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

hob*_*es3 283 vim

有时我想跨多行编辑某个可视文本块.

例如,我会采用如下所示的文本:

name
comment
phone
email
Run Code Online (Sandbox Code Playgroud)

让它像这样扯掉

vendor_name
vendor_comment
vendor_phone
vendor_email
Run Code Online (Sandbox Code Playgroud)

目前,我现在的方式是......

  1. 按下V然后按j4次选择所有4行块.
  2. 缩进>.
  3. 回去一封信h.
  4. 转到阻止视觉模式ctrlv.
  5. j4次选择向下4行.此时,您已选择了一个4x1的空白视觉块(4行,1列).
  6. c.请注意,这一列几乎向左缩进了一列.
  7. 输入" vendor_"没有引用的a.注意我们不得不放回的额外空间.
  8. esc.这是我用于esc退出插入模式的极少数时间之一.ctrlc只会编辑第一行.
  9. 重复步骤1.
  10. 用另一种方式缩进<.

如果在单词之前至少有一列空格,我不需要缩进.如果我不必清除视觉块,我就不需要空格c.

但是如果我必须清除,那么有没有办法在不创建所需的缩进空格的情况下执行上面执行的操作?

此外为什么用退出了插入模式编辑一次只能工作多行escctrlc

编辑:

这是一个更复杂的例子

name    = models.CharField( max_length = 135 )
comment = models.TextField( blank = True )
phone   = models.CharField( max_length = 135, blank = True )
email   = models.EmailField( blank = True )
Run Code Online (Sandbox Code Playgroud)

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 )
Run Code Online (Sandbox Code Playgroud)

在这个例子中,我将执行垂直视觉块.,然后在插入模式期间重新插入它,即类型.whatever..希望现在你可以看到这种方法的缺点.我仅限于在垂直位置选择一列完全相同的文本.

ick*_*fay 850

  1. 将光标移动到nin name.
  2. 进入视觉块模式(ctrlv).
  3. j三次(或3j).
  4. I(大写i).
  5. 输入vendor_.
  6. esc.

小型截屏演示了该方法

I必须使用大写而不是小写,i因为小写i被解释为文本对象的开头,这本身就很有用,例如用于选择标记块(it)内部:

迷你截屏显示it文本对象的有用性

  • 哇,我希望我能给你超过+1的动画GIF大声笑.不错的工作! (110认同)
  • 我无法在Windows中使用它(因为CTRL + V被映射为剪贴板粘贴).但是Vim还将此映射到Windows版本的**Ctrl + Q**. (11认同)
  • "esc"需要花费大量时间来处理,呃. (6认同)
  • @ANjaNA:如果你要插入的位置都在同一列中(例如,如果数字长度相同),你可以使用相同的技术,除了按下'A`而不是'I`,它将在选中后插入阻止而不是之前.但是,如果你的线条长度不同,那将无效; 我喜欢使用匹配每行末尾的替换,例如选择一些行并使用`:s/$/inserted /`. (4认同)
  • 按 esc 后我必须按向下箭头才能使其工作 (4认同)
  • 好一个.我不知道'我'. (3认同)
  • @Ven:在那段时间里,Vim并没有真正忙碌 - 只是等着你按下另一把钥匙,最终超时了.为您做两个实验:首先,尝试按下escape然后立即按下另一个键,如`j`或`^ L`.你应该看到Vim毕竟不忙; 它只是在等待.其次,尝试将[`'timeout'`](https://vimhelp.appspot.com/options.txt.html#%27timeout%27)更改为较低的值,如"80"(而不是默认的"1000")并观察它会更快地超时. (2认同)
  • @icktoofay看起来你要设置的变量是“timeoutlen”而不是“timeout”。 (2认同)
  • 这对于插入文本来说非常有效,但对于删除文本似乎不起作用,或者我做错了什么? (2认同)
  • 如果它确实不起作用,你会怎么做? (2认同)

小智 66

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

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

我发现这种技术通常比视觉块模式更快,适用于少量添加,并且还有一个额外的好处,即如果你不需要在一个范围内的每一行上插入文本,你可以通过按下extra来轻松跳过它们j. .

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


Lou*_*adi 36

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

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

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

  • 优秀!我只是强调像我这样的VIM noobs的最后一步`Esc` - 我花了一段时间才弄清楚这些变化会在"之后"传播! (2认同)
  • 很好,也不知道“A”和“C”选项。 (2认同)
  • 为什么这对“v”不起作用?我可以使用“Ctrl+V --&gt; A”来完成此操作,但是使用“v”来选择文本不起作用——“A”仅附加到该行。不是都选的吗?另外,非常奇怪——如果我将视觉块扩展到行尾,则“A”只会附加到行尾;否则,它将附加到每行可视块结束的位置。就像它无法识别“a”和“A”之间的区别一样。 (2认同)
  • 我需要使用“c”而不是“C”,但它工作得很好。谢谢 (2认同)

Bri*_*eal 29

我会使用宏来记录我的动作,然后重复它.

  1. 将光标放在名字的第一个字母上.
  2. 点击qq开始录制到q缓冲区.
  3. 点击i进入插入模式,然后键入vector_,然后点击ESC退出插入模式.
  4. 现在点击0回到行的开头.
  5. 现在打到j了下来.
  6. 现在q再次点击停止录制.

你现在有一个很好的宏.

键入3@q以执行宏3次以执行其余行.


sri*_*lla 26

:%s/^/vendor_/
Run Code Online (Sandbox Code Playgroud)

还是我错过了什么?

  • @dan如果只需要一个子文本,你可以将搜索限制为一组行号,例如`1,4s/^/vendor_ /` (8认同)
  • 这很有意思,但更实际的是用`V`直观地阻止选择并输入`:`.它将在ed表达式前加上`:'<,'>`,这使得ed仅适用于带有`:'<,'> s/^/vendor_ /`的选择. (8认同)
  • @BradKoch 有趣。我不知道行号限制,谢谢。 (2认同)

arc*_*don 12

2016年1月更新

虽然接受的答案是一个很好的解决方案,但实际上这个键击次数会少一些,并且可以更好地扩展 - 原则上基于已接受的答案.

  1. 将光标移动到nin name.
  2. 进入视觉块模式(ctrlv).
  3. 3j
  4. I.
  5. 输入vendor_.
  6. esc.

视觉图

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

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

在上面的例子中,这将是4G.但是,当处理几个行号时,显式计数效果很好.


Nis*_*ant 7

您可能还有一个用例要删除文本块并替换它.

像这样

Hello World

Hello World
Run Code Online (Sandbox Code Playgroud)

Hello Cool

Hello Cool
Run Code Online (Sandbox Code Playgroud)

您可以直观地在两行中选择"世界".

键入c进行更改 - 现在您将处于插入模式.

插入你想要的东西,然后点击逃脱.

两者都得到垂直反射.它的工作原理就像'我',除了它用新文本替换块而不是插入它.


Man*_*ish 6

假设你有这个文件:

something

name
comment
phone
email

somethine else
and more ...
Run Code Online (Sandbox Code Playgroud)

您想在"name","comment","phone"和"email"前面添加"vendor_",无论它们出现在文件中的哪个位置.

:%s/\<\(name\|comment\|phone\|email\)\>/vendor_\1/gc
Run Code Online (Sandbox Code Playgroud)

c旗帜将提示您确认.如果您不想要提示,可以删除它.


com*_*eak 6

我想在只有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. https://unix.stackexchange.com/questions/84929/uncommenting-multiple-lines-of-code-specified-by-line-numbers-using-vi-or-vim

  2. https://unix.stackexchange.com/questions/120615/how-to-comment-multiple-lines-at-once


Aub*_*gne 6

一个可以更灵活的替代方案:

示例:在行首输入文本 XYZ

:%norm IXYZ
Run Code Online (Sandbox Code Playgroud)

这里发生了什么事?

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

然后你点击Enter,它就会执行。

具体到您的要求:

:%norm Ivendor_
Run Code Online (Sandbox Code Playgroud)

您还可以选择特定范围:

:2,4norm Ivendor_
Run Code Online (Sandbox Code Playgroud)

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

:'<,'>norm Ivendor_
Run Code Online (Sandbox Code Playgroud)

  • 是否可以在插入模式(规范 Iabc&lt;ESC&gt;)下发送像 &lt;Esc&gt; 这样的按键序列,以便做更多有趣的事情? (2认同)
  • @batbrat 我刚刚想通了!你可以点击 `ctrl-v ctrl-[` 来插入一个“转义的 Esc”,它会将你拉回“正常模式”以执行正常命令。我刚刚用 `'&lt;,'&gt;norm Iaa^[ysiw"` 测试了这个,其中 `^[` 是转义的 Esc。 (2认同)

Arp*_*ini 5

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
Run Code Online (Sandbox Code Playgroud)

  • 奇怪的是,它现在对我有用。什么都没有改变,除了星星:)在寻找我的问题的解决方案时,我确实在这个页面上找到了一些东西,尽管它提到了在 vim 中寻找的东西 http://vim.wikia.com/wiki/Inserting_text_in_multiple_lines 在 Vim 中,通过输入 :version 命令检查您是否具有块操作符功能(I、A 等)。输出应包含+visualextra。 (2认同)