vim - 如何在不计算行数的情况下删除大块文本?

217
在vim中,我经常需要删除(或复制)大块的文本。可以使用命令计算文本的行数,例如使用50dd来删除50行。
但是,如果不知道要删除多少行文本,该如何删除这个大块文本呢?

1
如果窗口足够大,相对行号在这里非常有用。将光标放置在窗口顶部,找到要删除的最后一行的相对行号(假设为n),然后加1,接着输入该数字,再输入dd。例如,如果n=50,则输入51dd。或者,使用一个动作命令-- 50d<向下箭头> - BallpointBen
查找相对行号 - 或者使用 :set rnu 命令,Vim 将立即完成此操作!您所在的行仍将被绝对编号,但是光标上下的行将对称地编号为 1、2 等(并随光标移动、文件级事件等更新)。 - John P
对于在两个模式之间有多行变量的情况,我最终使用了Linux CLI中的sed命令...请参见https://dev59.com/cW015IYBdhLWcg3w9wp1#6287940 - bcag2
13个回答

333

请前往起始行输入ma(标记"a")。然后跳转到最后一行,输入d'a(删除至标记"a")。

这样将会删除所有当前行到标记行之间的行(包括标记行)。此方法适用于vivim编辑器,如果您的环境不支持后者,则也可以使用前者。


5
这真是太棒了!我讨厌做某些事情(比如数行数)很长时间后才去寻找更好的解决方案。谢谢! - ryanjdillon
1
真的很棒,我总是使用可视化模式来删除块,但这种方式更好 +1。 - hish
6
对于删除50万行以上的内容,我发现使用这种方法比可视化模式更有帮助。 - Michael
1
非常实用的答案。我用它来批量删除服务器中文件/var/mail/username中的邮件,并保留最后的邮件。我做一个标记,然后输入例如50000,接着输入gg跳转到第50,000行,然后删除所有中间的行。非常好用! - otmezger
1
@horta,我可能不会使用vim作为编辑千兆字节文件的工具 - 我倾向于选择像awk和它的同类文本处理工具 :-) - paxdiablo
显示剩余3条评论

309

我不是vim大师,但在这种情况下我使用的是“可视模式”。在命令模式下,输入V(大写)。然后使用上下移动键来突出显示您想要删除的块(所有常用的移动命令都有效)。然后使用xd删除它。


2
奇怪。我知道在Linux(vim 7.3.50)上和Windows上的gVim上它对我有效,并且根据其他答案,它也适用于其他人。也许你的.vimrc中的一些设置使它出问题了? - Mat
8
您可能需要澄清有两种可视化模式——Visual Line(CTRL-v)和Visual Block(Shift-v)。 - Justin Ethier
2
我经常这样做。但我总是认为这是作弊和不太理想的vim。 - Jim Mitchener
10
实际上有三种视觉模式:普通视觉模式(以字符为基础 {v}),视觉行模式(以行为基础 {S-v}),以及视觉块模式(允许选择块状内容 {C-v})。 - Tom Regner
在可视模式下,您还可以键入“/marker”以跳转到“marker”字符串并保留选择。 - E Ciotti
显示剩余2条评论

51

你也可以使用可视模式(某些命令也适用于删除选项)。 vip vap 选择段落,v2ap 选择两个段落。 dap 可以删除,d2ap 也可以。你可以在 [ ] 块中删除,例如 da[

类型的对象参考自 vim 文档:第 4 节。链接为:http://vimdoc.sourceforge.net/htmldoc/visual.html

4. Operating on the Visual area             *visual-operators*

...    
The objects that can be used are:
aw  a word (with white space)           
iw  inner word                  
aW  a WORD (with white space)           
iW  inner WORD                  
as  a sentence (with white space)           
is  inner sentence                  
ap  a paragraph (with white space)          
ip  inner paragraph                 
ab  a () block (with parenthesis)           
ib  inner () block                  
aB  a {} block (with braces)            
iB  inner {} block                  
a<  a <> block (with <>)                
i<  inner <> block                  
a[  a [] block (with [])                
i[  inner [] block                  

2
da[, da{, da" 都是程序员常用的符号。 - Rene Wooller
1
“dap” 很容易记住,因为它代表“删除一个段落”。 - Tropilio
我要把这个保存在某个地方!这太棒了! - Usman Sabuwala

39

这里有很多更好的答案,但为了完整性,我将提及在阅读上面提到的一些伟大答案之前我曾使用的方法。

假设您想从第24行到39行删除。您可以使用ex命令。

:24,39d

您也可以使用“yank”命令来复制行。

:24,39y

在24-39行之间找到并使用查找和替换功能

:24,39s/find/replace/g

13

这在一定程度上取决于那个大块是什么。如果您只想删除一个段落,则可以使用dip命令。


谢谢你的建议。不幸的是,我在处理代码,通常需要比那更精细的控制。 - Justin Ethier
1
我也在编写代码,我通过空行来分隔逻辑块。这个技巧让我的一天变得更美好了。现在我可以用三个按键删除大块的逻辑。 - miniml
它能够工作是因为“d”表示删除,“p”在这个上下文中表示段落。 - user98761

11

如果您通过 set number 打开行号功能,则只需使用 dNNG 即可从当前位置删除到第NN行。因此,您可以导航到要删除的行的开头,然后仅需使用 d50G ,假设这是您要删除的最后一行。


7

有几种可能性,最好的取决于您所处理的文本。

两种可能性如下:

  • 切换到可视模式(VS-V等),使用光标移动选择文本,然后按d键删除
  • 使用dap删除整个段落

现在我知道了 DAP 并且更喜欢它,因此我经常使用它,但是它总是删除一个块以及该块后面的空行,但是有没有一种方法可以删除该块以及该块前面的空行呢? - dansch
在带有段落的文本中间,结果中没有语法区别,对吗?如果有的话,我建议您编写一个新的问题,并且提供示例来阐述您的需求。 - Tom Regner

6

如果整个代码块在屏幕上可见,您可以使用relativenumber设置。请参阅:help relativenumber。7.3版本中提供。


直到我开始使用它,我才意识到:se rnu有多么有用——不仅适用于50dd,还适用于导航和50j。 - rshdev

5

对我来说,计算行数太繁琐了,但计算“段落”就不那么麻烦了。 '{' 和 '}' 分别将光标移动到光标前后的第一行空行。光标移动操作可以与删除操作结合使用,几个其他答案也采用了类似的方法(dd 删除一行,dG 删除文档末尾等)。
例如:

/* Lorem ipsum dolor sit amet, consectetur adipiscing elit. */

Lorem *ipsum(void) {
  return dolor(sit, amet);
}

如果你的光标在注释块上方,使用'd}'删除注释块,'d2}'则会同时删除注释块和代码块。如果你的光标在代码块下方,使用'd{'删除代码块,'d2{'则会同时删除代码块和注释块。当然,你可以先移动光标来跳过一个块:'{d{'或者'}d}'。
如果你的空格使用一致,或者你能够一目了然地数出段落数量,这个方法应该会起作用。如果你有兴趣,Vim帮助文件中还有更多关于光标的技巧。

3

您可以将光标放置在块的开头或结尾,进入可视化模式 (shift-v)。然后简单地向上或向下移动,直到所需的块被突出显示。最后,通过按 y 键复制文本,或按 d 键剪切文本。


可能有些奇怪,但是通过这个我找到了如何从某个期望的中点选择一行文本,并选择下面多行在同一点到每行结尾的文本。正是我所需要的。 - nanker

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