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

时间:2010-06-13 11:18:53

标签: regex vim

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

:g/^$/,/./-j

有人可以描述一下这是如何运作的吗?

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

1 个答案:

答案 0 :(得分:49)

这真的非常巧妙。让我们分解吧。 ex命令

g/^$/xyzzy

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

这里的棘手问题是你的xyzzy命令是另一个替换命令:

,/./-j

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

逗号为/./-后意味着搜索下一个字符(.表示任何字符),然后备份一行(/./-/./-1的缩写,因为如果没有给出值,则暗示一个)。你会在你操作的第一个非空白行上找到该模式.

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

然后执行该范围内的连接。

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

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

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

1 Line 1
2
3 Line 3
4 Line 4
5
6
7
8
9 Line 9

: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文档说明了一个两遍算法,一个用于标记行,一个用于执行操作。

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