怎么做:g/^ $ /,/./ - j(减少多个空行到一个空格)在vim中工作?

Mer*_*glu 27 regex vim

在文章Vim Regular Expressions中,Oleg Raisky给出了以下命令,将多个空白行减少为一个空白:

:g/^$/,/./-j
Run Code Online (Sandbox Code Playgroud)

有人可以描述这是如何工作的吗?

我知道:g命令和正则表达式.但我不明白这部分的/,/./-j作用.

pax*_*blo 51

它真的非常巧妙.让我们分解吧.该ex命令

g/^$/xyzzy
Run Code Online (Sandbox Code Playgroud)

将搜索所有空行并在每个空行上执行xyzzy命令(任意ex命令).

这里棘手的一点是xyzzy你的情况下的命令是另一个替代命令:

,/./-j
Run Code Online (Sandbox Code Playgroud)

,/./-指定的范围内.这是形式<start>,<end>,因为在逗号之前没有任何内容,它假定当前行(您找到空行的那一行)是开始.

逗号后是/./-,这意味着搜索下一个字符(.指任何字符)然后备份一条线(/./-是短期的/./-1,因为如果没有给定值的一个被隐含).您将.在您操作的第一个非空白行上找到该模式.

换句话说,范围的结尾是您当前操作之后或之后的最后一个空白行.

然后在该范围内执行连接.

如果范围的开始和结束相等(该部分中只有一个空行),则连接不执行任何操作.如果他们不平等,加入将全部加入他们.

这就是它将多个空白行合并为一个的方式.

让我们看一个例子(行号不在文件中):

1 Line 1
2
3 Line 3
4 Line 4
5
6
7
8
9 Line 9
Run Code Online (Sandbox Code Playgroud)

:g命令将找到所有空行并对它们执行操作(第2,5,6,7和8行).

对于第2行,,/./-j将设置2到2的范围(下一个.在第3行找到,然后减去1).2,2范围内的连接什么都不做.

对于第5行,,/./-j将设置范围从5到8(下一个.在第9行找到,然后减去1).5,8范围内的连接将将所有这些线连接在一起.

我不完全确定这一点,但我认为操作可能不会在作为早期操作的一部分消失的行上执行.那是因为处理循环中早期删除的行是没有意义的.

换句话说,因为删除了第6行到第8行(与第5行组合),所以全局命令在此之后不会对它们进行操作.我的基本原理是vim文档声明了一个两遍算法,一个用于标记行,一个用于执行操作.

可能在这一点上错了(这不是第一次),但它是一个不影响功能的实现细节.