使用块选择在vim中删除行末的内容

12

当我使用vim的块选择尝试从行末删除时,出现了异常行为。

假设我有这样一段文本:

delete this char:x
and this:x
also this:x
and then this:x
lastly this:x

如果我想在每一行末尾添加y,可以按以下步骤进行操作:
  • 使用C-v开始块选择
  • 使用4j选择所有行
  • 使用$移动到每行末尾
  • 使用A开始追加
  • 输入所需文本y
这样就会得到:
delete this char:xy
and this:xy
also this:xy
and then this:xy
lastly this:xy

但是,如果我尝试在最后一步中删除x而不是添加它,我希望得到以下结果:

delete this char:
and this:
also this:
and then this:
lastly this:

尽管我最终得到:
delete this char:
and this:x:
also this:x:
and then this:x:
lastly this:x:

据我所知,它会将第一行的最后一个字符附加到所有其他行(在这种情况下是),而不是删除缺失的字符(在这种情况下是x)。我可以使用宏或替换来完成此操作,但我不太理解这种行为背后的原理。是否有一种方法可以通过块选择来实现这个功能?

我不理解你所描述的行为。第一个 x 被移除,但没有添加任何内容。 - romainl
@romainl,你是否使用了与问题相同的示例?如果您使用类似“删除此字符:x”和“删除x”的内容,则会添加尾随空格,这可能很容易被忽略。 - none
不,我可以很好地看到尾随空格,并且没有任何空格。在这种情况下,<C-v>{movement}$A,无论如何都不会在选择中的每一行上删除字符。只有添加字符有效。如果你想听我的意见,这有点短视,但这就是它的设计方式。通常使用 :'<,'>norm $x:'<,'>s/x$// 来删除一系列行末的 x - romainl
4个回答

12

你是否尝试过:{range}normal? 这应该可以解决问题:

:'<,'>normal $x

当您键入:时,'<,'>部分会自动填充。


1
我认为对于上述解决方案的解释会非常有帮助。我尝试进行编辑,但被拒绝了。 - Jaakko
1
“{range}”是Vim帮助文件中相当常见的术语。 “normal”是一个命令,它输入以下内容,就像您在正常模式下键入它们一样。因此,总体而言,这个命令对于每一行都会执行以下操作:移动光标到行尾,然后删除光标下的字符。 - dash-tom-bang
注意:您需要使用“Ctrl + V”先选择一个可视块。 - wisbucky

6

$ C-v 4j x

  1. 将光标移到行末 $
  2. 切换进入可视块模式 C-v
  3. 向下移动(在本例中是 4 行) 4j
  4. 删除所选内容 x

编辑:(根据你的关于任意缩进的评论)

可以用一个简单的宏来完成。宏并不像你想象中那么难:

  1. 开始记录宏,我们将把它命名为“a”,输入 qa
  2. 将光标移到行末 $
  3. 删除一个字符 x
  4. 向下移动一行 j
  5. 结束宏录制 q

现在应用宏:20@a - 将重复执行录制宏时的操作,这里是重复 20 次。


这个可以工作,但我需要一些可以适用于任意缩进的东西。我已经相应地编辑了问题。 - none
宏解决方案的问题在于我必须数出需要修改的行数。 - Jaakko

6
如果我只需要处理少量数据,我通常使用 Abackspaceesc 的组合键。然后重复按 j. 直到完成。虽然这不是最快的方式,但很容易记住。
如果我需要处理大量数据,我通常使用可视化选择行的方式,通过 V 键进行操作,然后对选定范围进行替换或正常命令。
:'<,'>s/.$//
:'<,'>norm $x

注意:您不需要键入'<,'>。当您选择某些文本并开始命令时,它会自动插入。

替换命令非常简单,匹配最后一个字符(.$),然后将其替换为无。

普通命令就像在正常模式下删除最后一个字符一样,通过$x来删除单行除外,它将应用于范围内的每一行。

有关更多帮助,请参见:

:h range
:h :s
:h :norm

如果将其制作为宏,您可以重复任意次数,例如10@<register>而不是j.j.j.j.j.j.j.j.j.j.(4个按键而不是20个,再加上3个额外的按键来记录宏(q<register>...q))。 - Brian McCutchon

2

正如你自己所说,为了实现你的目标,还有其他更好的方法可供选择。例如:sq(macro):g/.../norm $x:s/.$//g非常直接。

Ctrl-V不适合这项工作。至于它的名字:VisualBLOCK。你想要删除最后的x,而它们(仅限x)不在一个块中。

然而,如果你真的想要坚持使用Ctrl-V,你需要做一些额外的工作,把那些‘x’放在一个块中。如果你安装了Align插件,你可以:

选择(V)你想要进行操作的所有行,

<leader>t:

那么你的文本看起来像这样:
delete this char : x
and this         : x
also this        : x
and then this    : x
lastly this      : x

按下 Ctrl-V 来删除 x,你应该知道如何操作。

然后

:%s/ *:/:/g

去掉冒号前的填充空格。

然而,我认为这不是一个好的方法。


这些都很好,但对我来说没有一个像视觉块一样直观。在放弃之前,我想把问题保持开放一段时间,因为我仍然觉得没有理由阻止实现这样的功能。 - none

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