捕获与搜索匹配的行的行号

Capture Line numbers of lines matching a search

示例:

搜索:

/lastword\s*\n\zs\(\s*\n\)\{6}\ze\s*startword

此搜索在以 "lastword" 结尾的行和以 "startword"

开头的行之间搜索 6 个空行

我想捕获与此搜索匹配的空行的行号。

vim有没有办法做到这一点?

您可以使用:g:number(或简称:#)打印出带有行号的行。

:g/lastword\s*\n\zs\(\s*\n\)\{6}\ze\s*startword/#

要捕获此内容,您必须使用 :redir 将输出重定向到其他地方。在下面的这种情况下,我们将其重定向到未命名的寄存器 (@")

:redir @"|execute 'g/pattern/#'|redir END

注意:必须将 :execute:g 一起使用,否则 redir END 将在使用 :g 命令的每个匹配行上执行。

现在这将通过 :# 开始行打印,这不是我们想要的(我们想要 foobar 之间的空行)。我们可以使用带有 :# 命令的范围来完成此操作。

:redir @"|execute 'g/foo\_.*bar/+,/bar/-#'|redir END

范围现在是 +,/bar/-,翻译为开始下一行 (+) 并搜索 bar (/bar/) 然后减去一行 (-).我们可能可以简化一些,因为我们知道空行的数量应该是 6。

:redir @"|execute 'g/foo\_.*bar/+#6'|redir END

我们可以通过将内容放入新缓冲区并删除多余的行来更进一步。

:redir @"|exe 'g/pattern/+#6'|redir END|new|pu|%s/\d\+\zs.*//|%le|g/^$/d

这里有很多事情要做,但我们的想法是捕获输出,打开一个新缓冲区,粘贴内容,然后清理输出。

备选方案

或者 awk 可能会使这更容易一些。 运行 当前 Vim 缓冲区中的以下内容:

:%!awk '/lastword\s*$/,/^\s*startword/ { if([=15=] ~ /^\s*$/) { print NR} }'

如需更多帮助,请参阅:

:h :g
:h :redir
:h :exe
:h :range
:h :new
:h :pu
:h /\zs
:h :le
:h :d