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

时间:2013-11-07 01:29:19

标签: regex vim

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

例如,我有一个文本文件,我用作实验室笔记本,不同日期的注释用短划线分隔。我可以用类似:% g/^-/d之类的东西来删除所有的虚线。但是,假设我想调整所有实际文本行的大小,而不是触及那些虚线。

对于单个段落,这将类似于{!}fmt。但是如何将其应用于所有非破折号段落?当我尝试看起来合乎逻辑的东西时,只需将这两个与:% v/^-/!fmt连在一起,那就行不通了。 (事实上​​,它似乎让Vim崩溃了......)

有没有办法连接这两个想法,只将与模式匹配的行(不是)传递给外部命令,如fmt

2 个答案:

答案 0 :(得分:3)

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

:global(和:v)两次通过缓冲区,

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

因此,如果您可以提出一个命令 - 无论是Ex命令还是命令行工具 - 以及可以应用于每个匹配行(和范围)的相关范围,您就有了胜利者。

例如,假设您的文字是软包裹的,并且您的段落只是以减号开头的行,这里是如何重新格式化段落:

:v/^-/.!fmt -72

这里我们使用范围."当前行"并通过 fmt 过滤每条匹配的行。更复杂的范围也有效。例如,如果您的文字是硬包装的,并且段落被定义为"从以减号开头的行,直到下一个空行"你可以改用它:

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

帮助主题:

答案 1 :(得分:1)

一种方法可能是将命令应用于匹配模式'不仅包含短划线'的行

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

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

编辑 我正在做一些实验,我认为recurvie宏应该适合你

首先设置nowrapscan:

set nowrapscan

防止递归宏执行超出你想要的次数。

然后你进行搜索:

/\v^(-+)@!

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

之后,开始录制宏

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

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

let @q .= '@q'

然后转到缓冲区的初始化以应用递归宏并进行修改:

gg@q

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