我最喜欢的两个Vim功能是能够将标准运算符应用于与正则表达式匹配的行,以及通过外部命令过滤选择或行范围的功能。但这两个想法能结合起来吗?
例如,我有一个文本文件,我用作实验室笔记本,不同日期的注释用短划线分隔。我可以用类似:% g/^-/d
之类的东西来删除所有的虚线。但是,假设我想调整所有实际文本行的大小,而不是触及那些虚线。
对于单个段落,这将类似于{!}fmt
。但是如何将其应用于所有非破折号段落?当我尝试看起来合乎逻辑的东西时,只需将这两个与:% v/^-/!fmt
连在一起,那就行不通了。 (事实上,它似乎让Vim崩溃了......)
有没有办法连接这两个想法,只将与模式匹配的行(不是)传递给外部命令,如fmt
?
答案 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^(-+)@!
测试按n
和p
是否适用于您的模式并在需要时进行调整
之后,开始录制宏
qqn:.!awk '{print $2}'^M$
在这种情况下,我使用awk作为示例.!
表示使用外部程序过滤当前行
然后,为了使宏递归,只需将字符串'@q'
附加到寄存器@q
let @q .= '@q'
然后转到缓冲区的初始化以应用递归宏并进行修改:
gg@q
然后你就完成了。希望这有帮助