Vim:如何将外部命令仅应用于行匹配模式



我最喜欢的两个 Vim 功能是能够将标准运算符应用于与正则表达式匹配的行,以及能够通过外部命令过滤选择或行范围的能力。但是这两种想法可以结合起来吗?

例如,我有一个用作实验室笔记本的文本文件,其中包含由一行短划线分隔的不同日期的笔记。我可以做一些事情,比如删除所有带有:% g/^-/d的破折线。但是,假设我想调整所有实际文本行的大小,而不触及这些虚线。

对于单个段落,这将类似于 {!}fmt .但是,这如何应用于所有非破折号段落呢?当我尝试看似合乎逻辑的事情时,只是将这两个与:% v/^-/!fmt链接在一起,这是行不通的。(事实上,它似乎使Vim崩溃...

有没有办法将这两个想法连接起来,并且只将匹配模式的行(不)传递到像fmt这样的外部命令中?

考虑:global命令的工作原理。

:global(和:v)通过缓冲区进行两次传递,

  • 首先标记匹配的每一行,
  • 然后在标记的行上执行给定的命令。

因此,如果您能想出一个命令(无论是 Ex 命令还是命令行工具)以及可以应用于每个匹配行(和范围)的相关范围,那么您就有了赢家。

例如,假设您的文本是软换行的,并且您的段落只是不以减号开头的行,以下是重新设置段落格式的方法:

:v/^-/.!fmt -72

在这里,我们使用"当前行"的范围,从而通过 fmt 过滤每个匹配行.。更复杂的范围也可以工作。例如,如果您的文本是硬换行的,并且段落被定义为"从以减号开始的行,直到下一个空白行",则可以改用以下内容:

:g/^-/.,'}!fmt -72

帮助主题:

  • :h multi-repeat
  • :h :range!
  • :h :range

一种方法可能是将命令应用于与模式"不包含破折号"匹配的行

我会尝试的解决方案是这样的(未经测试):

:g/v^(-+)@!/normal V!fmt

编辑我正在做一些实验,我认为递归宏应该适合您

首先设置nowrapscan:

set nowrapscan

防止递归宏执行的次数超出预期。

然后进行搜索:

/v^(-+)@!

测试按 np 是否适用于您的模式,并在需要时进行调整

之后,开始录制宏

qqn:.!awk '{print $2}'^M$

在这种情况下,我以awk为例.!表示使用外部程序过滤当前行然后,要使宏递归,只需将字符串'@q'附加到寄存器@q

let @q .= '@q'

并移动到缓冲区的开头以应用递归宏并进行修改:

gg@q

然后你就完成了。希望这有帮助

最新更新