【问题标题】:In Vim is there a way to delete without putting text in the register?在 Vim 中有没有办法在不将文本放入寄存器的情况下删除?
【发布时间】:2010-09-08 10:18:28
【问题描述】:

使用 Vim,我经常想用我刚刚拉出的代码块替换代码块。

但是当我删除要替换的代码块时,该块本身会进入寄存器,从而擦除我刚刚拉出的块。所以我养成了拉动,然后插入,然后删除我不想要的东西的习惯,但是对于大块代码,试图将插入的块和要删除的块分开会变得很混乱。

那么在 Vim 中替换文本最灵巧、最快捷的方法是什么?

  • 有没有办法删除文本而不将其放入寄存器中?
  • 有没有办法说例如“替换下一个单词”或“替换到下一段”
  • 还是以某种方式使用多寄存器功能的最佳方式?

【问题讨论】:

标签: vim replace vim-registers


【解决方案1】:

我在我的 vimrc 中加入了以下内容:

noremap  y "*y
noremap  Y "*Y
noremap  p "*p
noremap  P "*P
vnoremap y "*y
vnoremap Y "*Y
vnoremap p "*p
vnoremap P "*P

现在我从剪贴板寄存器中拉出和放入,不必关心默认寄存器会发生什么。另一个好处是我可以轻松地从其他应用程序粘贴。我知道我失去了一些功能(我不再能够管理剪贴板寄存器和默认寄存器的不同复制信息),但无论如何我无法跟踪多个寄存器/剪贴板。

【讨论】:

  • 除了所有这些重新映射之外,您还可以set clipboard=unnamedset clipboard=unnamedplus,将默认剪贴板分别更改为*+
  • @Steve 如果你这样做了,那么 d 也会将最后一个 yank 覆盖到剪贴板寄存器,这是问题试图避免的。
  • @79E09796,我并不是要暗示它会;我评论的是这个答案,而不是原来的问题。
  • 我把这些放在我的 .vimrc 中,现在 yanking 不起作用。知道为什么吗?
  • @tba 将 noremap 替换为 nnoremap(两个 n),它应该可以正常工作。
【解决方案2】:

noremap mm m

noremap mx "_x

是我的处理方式。

【讨论】:

    【解决方案3】:

    我发现一开始就拉入“p”缓冲区更容易。

    复制(又名:yank)

    # highlight text you want to copy, then:
    "py
    

    粘贴

    # delete or highlight the text you want to replace, then:
    "pp
    

    优点(与删除到特定寄存器相反):

    • "pp 触手可及
    • 不会在删除时意外覆盖粘贴缓冲区。

    【讨论】:

      【解决方案4】:

      主要问题是在可视模式下使用p。在可视模式粘贴内容后,以下函数将恢复未命名寄存器的内容。

       function! MyPaste(ex)
        let save_reg = @"
        let reg = v:register
        let l:count = v:count1
        let save_map = maparg('_', 'v', 0, 1)
        exec 'vnoremap _ '.a:ex
        exec 'normal gv"'.reg.l:count.'_'
        call mapset('v', 0, save_map)
        let @" = save_reg
      endfunction
      
      vmap p :<c-u>call MyPaste('p')<cr>
      vmap P :<c-u>call MyPaste('P')<cr>
      

      用法和以前一样,寄存器"的内容不变。

      【讨论】:

        【解决方案5】:

        您可以使用以下命令创建一个简单的宏: q"_dwq

        现在要删除下一个单词而不覆盖寄存器,可以使用@d

        【讨论】:

          【解决方案6】:

          有一个简单的映射很方便,它可以让你用缓冲区替换当前的选择。

          例如当你把它放在你的 .vimrc 中时

          " it's a capital 'p' at the end
          vmap r "_dP
          

          然后,在将某些内容复制到寄存器后(即使用“y”),您只需选择要替换的文本,然后在键盘上按“r”即可。所选内容将替换为您当前的寄存器。

          解释:

          vmap - mapping for visual mode
          "_d - delete current selection into "black hole register"
          P - paste
          

          【讨论】:

          • 更高级的版本,请查看:stackoverflow.com/questions/290465/…
          • 我想使用vmap &lt;C-P&gt; "_dP
          • 您可以只放置文本而不删除选择。例如,Vp 立即将您当前的行替换为被拉出的行。
          • 此解决方案无法解决经常用于删除的d 的问题。
          【解决方案7】:

          以下 vscode 设置应该允许,例如dd 和 dw 变成 "_dd 和 "_dw,现在可以在我们的重映射器中正常工作。

          {
               "vim.normalModeKeyBindingsNonRecursive": [
                  {
                      "before": ["d"],
                      "after": [ "\"", "_", "d" ]
                  }
              ]
          }
          

          【讨论】:

            【解决方案8】:

            寄存器 0 到 9 是您拉出或剪切等的最新内容,并且不包括已删除的内容等。因此,如果您拉出/剪切某些内容,它也在注册 0 中,即使您在那之后整天都说删除的内容,寄存器 0 仍然是您最后拉出/剪切的内容。

            yiw #同时进入默认寄存器和寄存器0

            它会拉出光标所在的单词

            删除的东西等将进入默认寄存器,但不会注册 0

            在标准模式下:

            "0p #放入寄存器0的内容

            在插入模式下:

            ctrl-r 0 #放入寄存器0的内容

            我还有一个朋友总是拉/切注册 x 哈哈。

            【讨论】:

            • 我已经知道viw,但从未意识到:ciw diw yiw
            【解决方案9】:

            Vim 偶尔偏爱复杂性而不是实用性,这给用户带来了应用寄存器来复制/删除操作的负担——通常情况下,人们只想粘贴复制的内容并“忘记”删除的内容。

            但是,与其对抗 vim 的复杂寄存器,不如让它们更方便:选择一个“默认”寄存器来存储您最近删除的内容。例如,将删除发送到 d 寄存器(让 a-c 打开以供临时使用;d 是一个很好的助记符):

            nnoremap d "dd           "send latest delete to d register
            nnoremap D "dD           "send latest delete to d register 
            nnoremap dd "ddd         "send latest delete to d register
            nnoremap x "_x           "send char deletes to black hole, not worth saving
            nnoremap <leader>p "dp   "paste what was deleted
            nnoremap <leader>P "dP   "paste what was deleted
            

            这种方法可以防止删除破坏 yanks 但不会放弃注册删除 - 可以粘贴(返回)已删除的内容,而不是将其丢失在黑洞中(如已接受的答案中所示)。在上面的示例中,这种召回是通过两个领导者 p 映射完成的。这种方法的一个好处是,它使您能够选择要粘贴的内容:(a) 刚刚拉出的内容,或 (b) 刚刚删除的内容。

            【讨论】:

            • 很好的解决方案。对我来说更直观的粘贴映射是nnoremap dp "dpnnoremap dP "dP
            • 这很棒。喜欢它。
            【解决方案10】:

            适用于将 JetBrans IDE(PhpStorm、WebStorm、IntelliJ IDEA)与 IdeaVim 一起使用的用户。您可能会遇到像nnoremap d "_d 这样的重新映射问题并使用它来删除一行dd。您可能的解决方案:nnoremap dd "_dd

            youtrack 有问题,请投票给他们: https://youtrack.jetbrains.com/issue/VIM-1189 https://youtrack.jetbrains.com/issue/VIM-1363

            【讨论】:

            • 非常感谢您抽出宝贵时间发布此回复。我曾在世界各地寻找过使用 IdeaVim 解决此问题的方法。
            【解决方案11】:

            我的情况:在Normal 模式下,当我使用x 按键删除字符时,这些删除会覆盖我最新的寄存器——我想使用x 删除字符并粘贴我在我的最近的注册(例如在两个或多个位置粘贴相同的文本)。

            我尝试了已接受答案 ("_d) 中的建议,但没有奏效。

            但是,从https://vi.stackexchange.com/questions/122/performing-certain-operations-without-clearing-register 接受的答案/cmets 中,我将此添加到我的~/.vimrc,它可以工作(您可能需要重新启动 Vim):

            nnoremap x "_x
            

            也就是说,我现在可以执行正常的 yank (y)、删除 (d) 和粘贴 (p) 命令,而且我使用 x 删除的字符不再填充最新的注册。

            【讨论】:

              【解决方案12】:

              对于 emacs-evil 用户,可以在粘贴后触发函数 (evil-paste-pop),并循环遍历 kill-ring 中的先前条目。假设您将它绑定到 &lt;C-p&gt;(Spacemacs 中的默认值),您将点击 p,然后根据需要点击尽可能多的 &lt;C-p&gt;

              【讨论】:

                【解决方案13】:

                对于那些对通过虚拟选择和粘贴替换文本时不覆盖未命名寄存器感兴趣的人。

                您可以使用以下简单且最适合我的解决方案:

                xnoremap &lt;expr&gt; p 'pgv"'.v:register.'y'

                来自这里的答案(和 cmets): How to paste over without overwriting register

                它首先通过选择,然后再次选择带有新文本的选择 (gv)。现在最后在可视模式下使用的寄存器(通常是未命名的寄存器,但如果您使用另一个寄存器进行粘贴,也可以无副作用)。然后再次将新值拉到寄存器中。

                PS:如果您需要一个更简单的变体,它也可以与 intellj idea 插件 vim-simulation 一起使用,您可以使用这个(缺点:即使为粘贴提供了另一个寄存器,也会覆盖未命名的寄存器):

                vnoremap p pgvy

                【讨论】:

                  【解决方案14】:

                  VIM 文档:编号寄存器 0 包含来自最近的 yank 命令的文本, 除非命令用 ["x] 指定另一个寄存器。

                  例如我们拉出“foo”并删除“bar”——注册表 0 仍然包含“foo”!因此可以使用"0p 粘贴“foo”

                  【讨论】:

                    【解决方案15】:

                    默认情况下,所有 yank 和 delete 操作都会写入未命名的寄存器。但是,最近的 yank 和最近的删除总是(单独)存储在编号的寄存器中。寄存器 0 保存最新的 yank。寄存器 1-9 保存 9 个最近的删除(1 是最近的)。

                    换句话说,删除会覆盖未命名寄存器中最近的 yank,但它仍然存在于 0 寄存器中。 中提到的黑洞寄存器技巧 ("_dd)其他答案有效,因为它可以防止覆盖未命名的寄存器,但这不是必需的。

                    您使用双引号引用一个寄存器,因此可以这样粘贴最近提取的文本:

                    "0p
                    

                    这是一个很好的参考:

                    【讨论】:

                      【解决方案16】:

                      针对懒人的微创解决方案:

                      注册 0 总是包含最后一个 yank(Rafaelalex2k8idbrii 已经提到过)。不幸的是,一直选择寄存器0 会很烦人,所以如果p 默认使用"0 会很好。这可以通过将以下几行放入您的 .vimrc 来实现:

                      noremap p "0p
                      noremap P "0P
                      for s:i in ['"','*','+','-','.',':','%','/','=','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
                          execute 'noremap "'.s:i.'p "'.s:i.'p'
                          execute 'noremap "'.s:i.'P "'.s:i.'P'
                      endfor
                      

                      第一行将每个p 笔划映射到"0p。但是,这会阻止p 访问任何其他寄存器。因此,所有带有显式选择寄存器的p 笔划都映射到 for 循环内的等效命令行表达式。 P 也是如此。

                      这种方式保留了标准行为,除了隐式的pP 笔划,现在默认使用寄存器0

                      提示 1: 剪切命令现在是 "0d 而不仅仅是 d。但是由于我很懒,这对我来说太长了;)因此我使用了以下映射:

                      noremap <LEADER>d "0d
                      noremap <LEADER>D "0D
                      

                      前导键默认为\,因此您可以通过键入\d\D 轻松剪切文本。

                      提示 2: 多键映射的默认超时时间非常短。您可能希望增加它以在选择寄存器时有更多时间。详情见:help timeoutlen,我正在使用:

                      set timeout timeoutlen=3000 ttimeoutlen=100
                      

                      【讨论】:

                        【解决方案17】:

                        我发现了一个非常有用的映射:

                        xnoremap p "_dP
                        

                        被删除的文本被放入“黑洞寄存器”,而被抽出的文本仍然存在。

                        来源:http://vim.wikia.com/wiki/Replace_a_word_with_yanked_text

                        【讨论】:

                          【解决方案18】:

                          对于 Dvorak 用户,一种非常方便的方法是将不需要的文本删除到“1 寄存器而不是“_黑洞寄存器”中,如果只是因为您可以使用相同的 shift 键和快速的小指动作按“+1”因为 1 是 Dvorak 中 " 正上方的键(另一方面,加号 d 使整个命令快得要命)​​。

                          当然,“1 寄存器可以用于其他用途,因为它很方便,但除非您有比替换文本更常见的目的,否则我会说这是一个很好的寄存器用途。

                          【讨论】:

                            【解决方案19】:

                            要删除某些内容而不将其保存在寄存器中,您可以使用“黑洞寄存器”:

                            "_d
                            

                            当然,您也可以使用其他任何不包含您感兴趣的任何内容的寄存器。

                            【讨论】:

                            • 一开始我以为这个命令不能正常工作。然后我意识到我使用的是美式键盘的“死键”版本。使用这种键盘布局,我必须输入"&lt;space&gt;_d。实际键入 ". 需要空格
                            • 关于仅在空行上选择性地执行此操作的任何想法? (如果我在空行上dd 它会进入黑洞,否则它会像平常一样dds)。
                            • 要删除一个字符,请尝试:"_x
                            • 这是标准文本编辑器胜出的一个领域。您只需按删除键。
                            • 您也可以使用yy 或'3yy'(或其他)来拉取某些东西,这会将其放入未命名的寄存器中,但也可以放入0。然后您可以继续使用"0p 粘贴它,尽管在那之后使用了d
                            【解决方案20】:

                            是的。这比先删除“旧”文本稍微复杂一些,但是:

                            我从...开始。

                            line1
                            line2
                            line3
                            line4
                            
                            old1
                            old2
                            old3
                            old4
                            

                            shift+v选中第1行、第2行、第3行和第4行,用d命令删除

                            然后我以同样的方式删除旧的 1-4 行。

                            然后,做

                            "2p
                            

                            这将粘贴倒数第二行(第 1-4 行)。 "3p 将执行倒数第三个,依此类推..

                            所以我结束了

                            line1
                            line2
                            line3
                            line4
                            

                            参考: Vim documentation on numbered register

                            【讨论】:

                            • 如果你用 选择行,你只用 d 删除它们,而不是 dd
                            • 1 到 9 适用于删除。要粘贴最后一个真正被拉出的东西(用'y'),你必须使用“0p。这在你首先拉出一些打算替换其他东西的东西,然后其他东西覆盖默认粘贴寄存器的情况下很有用。
                            • 欲了解更多撤消复杂性,请查看the Gundo (graphical undo) script
                            • @RafaeldeF.Ferreira:您的评论不是这个问题的答案,但它实际上可能解决了导致 OP 首先提出问题的实际问题。对我来说,这才是真正的问题。
                            【解决方案21】:

                            我在正确的上下文中使用的两个解决方案是:

                            • 使用 Vims VISUAL 模式突出显示要替换的内容,然后粘贴寄存器。

                            我使用这个主要是出于习惯,因为我很久以后才找到第二个解决方案,例如

                            yiw   " yank the whole word
                            viwp  " replace any word with the default register
                            
                            • YankRing。使用此插件,您可以使用键绑定&lt;ctrl&gt;+&lt;p&gt; 将之前编号的寄存器替换为您刚刚粘贴的寄存器。

                            基本上你可以按照自己的意愿进行粘贴,但是当你意识到你已经覆盖了默认寄存器从而丢失了你真正想要粘贴的内容时,你可以&lt;C-P&gt; 从 YankRing 历史记录中查找和替换!

                            其中一个必须有插件...

                            【讨论】:

                              【解决方案22】:

                              强调一下EBGreen said

                              如果您在选择文本时粘贴,则所选文本将替换为粘贴的文本。

                              如果您想复制一些文本然后将其粘贴到多个位置,请使用"0p 进行粘贴。编号寄存器 0 包含来自最近的 yank 命令的文本。


                              此外,您可以列出所有寄存器的内容:

                              :registers
                              

                              当您执行dbr's answer 之类的操作时,该命令可以更轻松地确定您想要的寄存器。您还将看到 /,%,# 寄存器。 (另见:help registers


                              最后,查看cWcW 以更改包含和不包含尾随空格的单词。 (使用大写 W 包括标点符号。)

                              【讨论】:

                                【解决方案23】:

                                我经常会犯错误,当我按照命令 'y'ank 然后 '"_d'elete into a black hole 然后 'p'aste。我更喜欢 'y'ank,然后按我喜欢的方式删除,然后 '" 0p' 来自 0 寄存器,这是最后复制的文本被推送到的位置。

                                【讨论】:

                                  【解决方案24】:

                                  在 Windows 版本中(也可能在 Linux 中),您可以使用 "*y 拉入系统的复制/粘贴缓冲区(即在拉出命令前加上双引号和星号)。

                                  然后您可以正常删除可替换行并使用"*p 粘贴复制的文本。

                                  【讨论】:

                                    【解决方案25】:

                                    对于“替换单词”,请在正常模式下尝试cw

                                    对于“替换段落”,请在正常模式下尝试cap

                                    【讨论】:

                                    • 对于“替换下一段”,请在正常模式下尝试c}
                                    • 为什么“cap”会这样? “a”和“p”不是代表“追加”和“粘贴”吗?
                                    • @WiSaGaN "ap" 代表“一段”:vimhelp.appspot.com/motion.txt.html#object-select
                                    【解决方案26】:

                                    文本被删除,在插入模式下,不会进入默认寄存器。

                                    【讨论】:

                                    • 但在默认模式下删除大量文本会很慢
                                    【解决方案27】:

                                    如果您使用 Vim,那么您将拥有可视模式,就像选择一样,但分离模式是 vi/vim 的基础。

                                    您要做的是使用可视模式选择源,然后拉动,然后再次使用可视模式选择目标范围,然后从默认缓冲区粘贴到文本。

                                    例子:

                                    在一个文本文件中:

                                    1| qwer 2|自卫队 3| zxcv 4|呸呸呸

                                    使用以下序列:ggVjyGVkp 你将结束:

                                    1| qwer 2|自卫队 3| qwr 4|自卫队

                                    解释:

                                    • gg: 去第一行
                                    • V:以整行启动视觉模式
                                    • j: 向下一行(选择从前一行开始,这会使选择向下一行)
                                    • y: 拉到默认缓冲区(选择的两条线,它会自动退出可视模式)
                                    • G:转到最后一行
                                    • V:开启视觉模式(和之前一样)
                                    • k:上升一行(和以前一样,启用可视模式,这会将选择增加一行)
                                    • p:粘贴(选择最后两行,它将用缓冲区中的任何内容替换这些行——在这种情况下是前两行)

                                    这有点不方便,将最后一个块放在缓冲区中,因此在某种程度上不希望重复粘贴相同的东西,因此您需要将源代码保存到命名缓冲区,例如 "ay (到一个名为“a”的缓冲区)并用"ap之类的东西粘贴(但是如果你正在编程,你可能不想粘贴多次,而是创建一个函数并调用它,对吧??)。

                                    如果你只使用 vi,那么你将不得不使用隐形标记而不是视觉模式,:he mark 更多关于这个,对不起,我对这个隐形标记不是很好,我被视觉模式污染了。

                                    【讨论】:

                                      【解决方案28】:

                                      对于您给出的具体示例,如果我理解这个问题,那么这可能会起作用:

                                      *Highlight what you want to put somewhere else
                                      *delete (d)
                                      *Highlight the code that you want it to replace
                                      *paste (p)
                                      

                                      【讨论】:

                                      • 这很好用,除非你想粘贴多个选择。
                                      【解决方案29】:

                                      好吧,首先执行以下命令:

                                      :h d
                                      

                                      然后你会意识到你可以删除到一个特定的寄存器。这样您就不会更改默认寄存器中的内容。

                                      【讨论】:

                                      • ["x]d{motion} Delete text that {motion} moves over [into register x] -- Vim :h d
                                      猜你喜欢
                                      • 2014-04-17
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2022-11-28
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2012-01-10
                                      • 2011-04-13
                                      • 2020-12-10
                                      相关资源
                                      最近更新 更多