你能在vi/vim中抓取或删除括号之间的内容吗?

155
在C语言中,给定以下代码行:

printf("%3.0f\t%6.1f\n", fahr, ((5.0/9.0) * (fahr-32)));

有没有一种方法可以从第一个粗体括号到其匹配括号进行删除或复制?我想到了df),但这只能让您到达9.0后面。
是否有类似的方法可以让vim获取匹配大括号之间的所有内容,而不管换行符?
7个回答

286

关于 dibdi( 呢。

它会删除光标所在的 内部 (...) 区块。

我喜欢文本对象 的动作和选择!


12
幸运的是,当我谷歌搜索这个问题时,这个问题是第一个结果 - 我不知道这个答案已经救了我多少次。而我总是会忘记它... :-(Translated: 幸运的是,当我在谷歌搜索这个问题时,它是第一个结果 - 我不知道这个答案已经帮了我多少次。然而我总是会忘记它... :-( - Konrad Rudolph
22
可以删除括号吗?(是的,我回答了自己的问题:dab表示删除一个块(包括它的括号)) - bantic
5
我投赞成票。此外,如果您想更正括号中的单词,请使用ciw - Developer Marius Žilėnas
5
+1!最近我发现文本对象运动时,我被震惊了!不再需要尝试将光标定位在正确的位置上以扯取文本:D - verboze

184

各种动作:%

% 命令 可以跳转到光标下的项目匹配项。将光标定位在开放(或关闭)括号上,使用 y% 进行复制或使用 d% 删除从光标到匹配括号的所有内容。

这是因为 % 是一个“运动命令”,所以它可以在 vim 需要这样的命令的任何地方使用。来自 :help y

["x]y{motion}       Yank {motion} text [into register x].  When no
                    characters are to be yanked (e.g., "y0" in column 1),
                    this is an error when 'cpoptions' includes the 'E'
                    flag.

默认情况下,“item”包括括号、大括号、圆括号、C风格的注释和各种预编译语句(#ifdef等)。

有一个“扩展匹配”插件,你可以在Vim主页上找到。

你可以通过在命令模式下输入:help various-motions来阅读有关 % 和相关运动命令的文档。

object-select

还有一组运动命令,你可以在可视模式下使用它们来选择不同的文本对象。

要解决你的具体问题,你需要执行以下操作:

printf("%3.0f\t%6.1f\n", fahr, ((5.0/9.0) * (fahr-32)));
                                   ^

假设您的光标位于^处。输入以下序列以选择您要查找的部分:
v2a)

首先进入可视模式,然后指定要向上跳 2 层圆括号。最后使用 a) 选择“一个块”。之后,您可以使用 dx 进行删除等操作。

如果您不想包含外部圆括号,则可以使用“内部块”代替:

v2i)

请参阅:help object-select,查看所有相关命令的完整列表。

谢谢!我知道百分号可以在匹配项之间切换;但是我不知道它在命令中也很有用。+1并接受。 - romandas
6
有趣,我一直认为 a 是指“周围”而不是“a”。感觉它更好地补充了“内部”。似乎每天都能学到新的Vim知识。 - Andrew Marshall

48
要删除括号内的所有内容,您可以始终使用 di( 及其衍生词。

注意 :

如 @porglezomb 在评论中建议的那样,您可以使用 a("along with")而不是 i("inside")来包括括号。因此,使用 da( 删除 () 中的所有内容,包括 ()

删除最外层括号内的文本:

因此,对于这行代码:

printf("%3.0f\t%6.1f\n", fahr, ((5.0/9.0) * (fahr-32)));
                                ^       ^
                                |       |
                                 \_______\___---> Cursor range

假设您的光标位于上述光标范围内,您可以执行以下命令:
di(   --> Deletes '5.0/9.0'
ci(   --> Substitutes '5.0/9.0'
yi(   --> Yanks '5.0/9.0'

删除第n个最外层括号内的文本:

要获取第n个最外层括号内的所有内容,只需在上述命令前添加n。因此,在与上面相同的光标位置下,

2di(   --> Deletes '(5.0/9.0) * (fahr-32)'
2ci(   --> Substitutes '(5.0/9.0) * (fahr-32)'
2yi(   --> Yanks '(5.0/9.0) * (fahr-32)'

3di(   --> Deletes '"%3.0f\t%6.1f\n", fahr, ((5.0/9.0) * (fahr-32))'
3ci(   --> Substitutes '"%3.0f\t%6.1f\n", fahr, ((5.0/9.0) * (fahr-32))'
3yi(   --> Yanks '"%3.0f\t%6.1f\n", fahr, ((5.0/9.0) * (fahr-32))'

5
请添加一条说明,提到 ai 的对应物,因为这有助于很多人理解。 - porglezomp
@romandas 这应该是被采纳的问题。我今天正在寻找完全相同的问题,而@Kevin是唯一给出正确答案的人。当然,我可以“滥用”来解决这个问题,但这需要更多时间,并且在我看来,只应用于更复杂的情况。删除特定范围内的内容正是di的用例。 - daniel451

21
你可以使用 d% 删除,使用 y% 复制。

4
“%” 是匹配括号或大括号的移动位置指示符。任何移动指示符都可以与“d”和“y”(以及其他许多操作)配对使用。 - chaos

11

将光标放在第一个括号上,然后按下v%yv%d


3
好的!% 跳转到匹配的括号。所以你甚至可以使用 d% 和 y%。 - unbeknown
1
请注意,'d%'可以从函数名的开头开始,并将删除整个函数调用。它也适用于'{}','[]'甚至'<> '对。 - Jonathan Leffler
@Leffler,感谢您的建议!知道在可视模式下百分号也可以使用是很好的。 - strager

4

尝试使用 ci[block-surrounder]

在您的情况下,将光标放置在您高亮显示的两个括号之间,并尝试按键:ci(


几乎了。经过测试,看起来光标需要在第一个括号上,而不是中间,并且“c”是更改命令。将光标放在开括号上,“di(”删除到匹配的闭括号,“yi(”复制。 - Richard Neish
1
ci 命令一直对我很有效。我所需要做的就是确保光标位于括号之间,这些括号包围着我需要删除的文本块。 - Justin Nguyen

3
如 David Norman 的回答所述,

将光标放在第一个括号上,然后按下v%yv%d

来自http://vimdoc.sourceforge.net/htmldoc/vimindex.html的解释:
标记               字符             备注  正常模式下的操作        
------------------------------------------------------------------------------
|v|                v                   开始字符为单位的可视模式
|%|                %                1  查找本行中下一个(花括号/方括号)括号并跳到它的匹配项,或跳转到匹配的注释括号,或跳到匹配项
|d|                ["x]d{motion}    2  删除Nmove文本[到缓冲区x]
这意味着它会选择两个括号之间和包括它们之间的所有内容(%),同时在视觉上向您显示选择内容(v),然后将其复制/粘贴y或删除/剪切d。(到默认缓冲区。)
使用p可以进行粘贴。
回答了这个问题,"教我自己钓鱼"

请注意:vimdoc.sourceforge.net是从vim.org链接过来的,而vim.org是截至2015年官方的vim网站。 - n611x007

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