【问题标题】:Vim: insert the same characters across multiple linesVim:在多行中插入相同的字符
【发布时间】:2012-03-21 22:13:46
【问题描述】:

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

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

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_"。请注意我们必须放回的额外空间。
  8. Esc。这是我使用 Esc 退出插入模式的极少数情况之一。 Ctrlc 只会编辑第一行。
  9. 重复步骤 1。
  10. 使用 以另一种方式缩进。

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

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

另外,为什么一次编辑多行只能通过 Esc 而不是 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 )

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

【问题讨论】:

  • 更好的方法:":%s/^/vendor_/"
  • 感谢您的回复。如果我只想在每一行附加一个单词,那就行了。但是我使用的方法可以在任何位置进行。让我用一个更复杂的例子添加另一个我的例子。
  • 然后使用 shift-V 突出显示要更改的行,并键入适当的搜索和替换命令 - 在第二个示例中,:s/models\./\0whatever./
  • 实现上述的方法很多。要完全回答问题的所有部分,然后是第 1 部分)我编辑的正则表达式或可视模式 esc 与答案中提供的一样工作得很好(我更喜欢 GVIM 中的可视选择)。对于第 2 部分),宏可能是 Brian Neal 提供的最简单的方法。我所知道的所有这些“操作方法”的最佳资源是 Drew Neil 的 Practical Vim。每当您忘记公式时,都是出色的快速阅读和轻量级参考。希望这个建议对某人有所帮助,对于许多 vim 用户来说,这将是值得的。
  • @Paul:如果你是counting keystrokes,你可以用&替换\0

标签: vim


【解决方案1】:
  1. 将光标移动到name中的n
  2. 进入可视块模式 (Ctrlv)。
  3. j三次(或3j)向下跳3行; G(大写g)跳转到最后一行
  4. I(大写 i)。
  5. 输入vendor_。注意:它只会更新 first 行中的屏幕 - 直到按下 Esc (6.),此时所有行都将已更新。
  6. Esc

必须使用大写的I 而不是小写的i,因为小写的i 被解释为text object 的开头,这本身就非常有用,例如用于在标签块内进行选择 (it):

【讨论】:

  • 我无法让它在 Windows 中工作(因为 CTRL+V 已映射为剪贴板粘贴)。但是对于 Windows 版本,Vim 也将其映射到 Ctrl+Q
  • @Ven:Vim 在那段时间实际上并不忙——它只是在等你按另一个键,最终超时。为您准备两个实验:首先,尝试按 Escape,然后立即按另一个键,例如 j^L。你应该看到 Vim 并不忙。它只是在等待。其次,尝试将'timeout' 更改为较低的值,例如80(而不是默认的1000)并观察它超时更快。
  • @icktoofay 看起来您要设置的变量是timeoutlen 而不是timeout
  • @ANjaNA:如果您要插入的位置都在同一列中(例如,如果数字都是相同的长度),您可以使用相同的技术,除了按 A 而不是 @987654342 @,它将在所选块之后而不是之前插入。但是,如果您的线条长度不同,那就行不通了;我喜欢使用与每行末尾匹配的替换,例如选择一些行并使用:s/$/inserted/
  • 我必须在按 esc 后按向下箭头才能使其工作
【解决方案2】:

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

  1. 将光标放在name中的第一个字母上。
  2. 点击 qq 开始录制到 q 缓冲区。
  3. 点击i进入插入模式,输入vector_,然后点击Esc退出插入模式。
  4. 现在点击 0 回到行首。
  5. 现在点击 j 向下移动。
  6. 现在再次按 q 停止录制。

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

键入 3@q 以执行您的宏 3 次以完成其余的行。

【讨论】:

  • “q”是特殊的(对于“快速宏”吗?)?
  • 如何使宏持久化(跨多个会话工作)?
  • @PeterMortensen Vim 有一个称为会话的功能,它可以保存缓冲区(以及许多其他内容),您可以查看它们。
  • 从一个彼得到另一个,很好的答案!
【解决方案3】:

假设你有这个文件:

something

name
comment
phone
email

something else
and more ...

您想在“姓名”、“评论”、“电话”和“电子邮件”前面添加“供应商_”,无论它们出现在文件中的什么位置

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

c 标志将提示您进行确认。如果你不想要这个提示,你可以放弃它。

【讨论】:

    【解决方案4】:

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

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

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

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

    【讨论】:

    • 很高兴看到另一种方法。
    • 我只喜欢这几行。更容易执行 IMO。
    • 输入你想要的前缀后,你不需要按escape键吗?
    • @iamnotsam,如果您处于插入模式,那么是的,您需要在移动到下一行之前按 Esc。否则按“。”只会插入一个句点。
    【解决方案5】:
    :%s/^/vendor_/
    

    还是我错过了什么?

    【讨论】:

    • 您错过了这样一个事实,即它可能是文件中的一个潜台词,其中包含不需要 vender_ 前缀的许多其他行。
    • @dan 如果只需要一个潜台词,可以限制搜索到一组行号,例如1,4s/^/vendor_/
    • @BradKoch 有趣。我不知道行号限制,谢谢。
    • 这很有趣,但更实用的是用V 直观地阻止选择并输入:。它将在 ed 表达式前面加上 :'&lt;,'&gt;,这使得 ed 仅适用于带有 :'&lt;,'&gt;s/^/vendor_/ 的选择
    • 如果您像我一样突出显示匹配项,您可能需要在之后运行:noh
    【解决方案6】:

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

    像这样

    Hello World
    
    Hello World
    

    Hello Cool
    
    Hello Cool
    

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

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

    插入你想要的东西,然后点击退出。

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

    【讨论】:

      【解决方案7】:

      2016 年 1 月更新

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

      1. 将光标移至name中的n
      2. 进入可视块模式 (ctrlv)。
      3. 3j
      4. I
      5. 输入vendor_
      6. esc

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

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

      在我们上面的示例中,这将是 4G。然而,当只处理几个行号时,显式计数效果很好。

      【讨论】:

        【解决方案8】:
        1. 使用 CtrlV 选择要修改的行。
        2. 按:

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

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

        【讨论】:

        • 太棒了!我只想为像我这样的 VIM 新手突出显示最后一步 Esc - 我花了一段时间才发现这些更改会“稍后”传播!
        • 很好,我也不知道“A”和“C”选项。
        • 为什么这不适用于v?我可以用Ctrl+V --&gt; A 来做,但是用v 来选择文本不起作用——A 只会附加到该行。不是都选吗?另外,很奇怪——A 仅在我将可视块扩展到行尾时才附加到行尾;否则它会附加到每一行的可视块结束的任何地方。就好像它无法识别 aA 之间的区别。
        • 我需要使用c 而不是C,但效果很好。谢谢
        【解决方案9】:
        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 后似乎什么都没有发生。
        • 奇怪的是,它现在对我有用。什么都没有改变,除了星星 :) 在寻找我的问题的解决方案时,我确实在这个页面上找到了一些东西,尽管它提到了在 vim 中寻找的东西 vim.wikia.com/wiki/Inserting_text_in_multiple_lines 在 Vim 中,检查你是否有块操作符功能( I、A 等)通过输入 :version 命令。输出应包括 +visualextra。
        • 我的意思是一般性地添加评论,而不是您的答案。这些答案中的大多数都说了同样的话,但使用了不同的词。我的提供了一些不同的东西,并包含了一个链接。
        【解决方案10】:

        我想在只有 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

        【讨论】:

        • 这对我来说是完美的解决方案,因为我经常只使用 vim-tiny。
        【解决方案11】:
        1. Ctrl + v 进入视觉块模式
        2. 使用上下箭头选择行
        3. 输入小写3i(按小写I三次)
        4. I(按大写I。这将带您进入插入模式。)
        5. 写下你要添加的文字
        6. Esc
        7. 按向下箭头

        【讨论】:

          【解决方案12】:

          一种更灵活的替代方案:

          示例:在行首输入文本 XYZ

          :%norm IXYZ
          

          这里发生了什么?

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

          然后你按Enter,它就会执行。

          具体到您的要求:

          :%norm Ivendor_
          

          您还可以选择特定范围:

          :2,4norm Ivendor_
          

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

          :'<,'>norm Ivendor_
          

          或对匹配“目标”正则表达式的每一行执行:

          :%g/target/norm Ivendor_
          

          【讨论】:

          • 是否可以在插入模式(标准 Iabc)下发送像 这样的键序列来做更多有趣的事情?
          • @batbrat 我刚刚想通了!您可以点击ctrl-v ctrl-[ 插入“转义的 Esc”,这会将您拉回“正常模式”以执行正常命令。我刚刚用'&lt;,'&gt;norm Iaa^[ysiw" 对此进行了测试,其中^[ 是转义的Esc。
          • :%mode 方法非常值得了解。我很高兴我偶然发现了这个答案!
          【解决方案13】:

          我来这里是为了在多行中粘贴一个已经复制的字符串。当使用y 复制时,我们可以粘贴,在插入模式下,按 Ctrl+r 并在按 '' 之后立即粘贴。这将与处于正常模式下的结果相同,然后按 p。这称为从注册表粘贴。

          假设缓冲区中有以下文本:

          vendor_something
          
          text
          to_receive
          the_paste
          pattern
          

          然后我们可以将光标指向vendor_中的v并按v,使用l向右移动,直到选中我们要粘贴在下面的文本中的下划线符号.之后,我们可以将光标指向“text”的开头(vendor_something下面的两行)并按Ctrl+v。然后I 进入插入模式,我们按下3j Ctrl+r '' Esc。此序列的结果将是:

          vendor_something
          
          vendor_text
          vendor_to_receive
          vendor_the_paste
          vendor_pattern
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-12-07
            • 2011-10-19
            • 1970-01-01
            • 2010-11-16
            相关资源
            最近更新 更多