:g /^$/,/./- j(将多个空行减少为一个空行)在vim中如何工作?


21

在《Vim正则表达式》一书中,Oleg Raisky提供了以下命令以将多个空行减少为一个空白:

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

有人可以说明这是如何工作的吗?

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

Answers:


24

确实是很巧妙。让我们分解一下。该ex命令

g/^$/xyzzy

将搜索所有空行并在每个空行上执行xyzzy命令(任意ex命令)。请注意,这xyzzy不是真正的 ex命令,仅在下一段中作为占位符存在。

棘手的是,xyzzy您的情况下的“命令”是另一个搜索命令:

,/./-j

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

在逗号之后/./-表示要搜索下一个字符(.表示任何字符),然后备份一行(这/./-是缩写,/./-1因为如果未指定值则表示该字符)。您将在要操作的模式.之后的第一行非空白行中找到该模式。

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

然后在该范围内执行联接。

如果范围的起点和终点相等(该节中只有一个空白行),那么join将不执行任何操作。如果它们不相等,join将把它们全部加入。

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

让我们看一个例子(行号仅用于说明,它们不在实际文件中):

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,2上的联接不执行任何操作。

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

该操作不会在作为早期操作一部分而消失的行上执行。这是因为处理在周期中早些时候删除的行是没有意义的。

换句话说,由于第6至8行被删除(与第5行结合),因此之后全局命令将不会对其进行操作。

这是基于以下事实:vim文档陈述了一种两遍算法,一种用于标记行,另一种用于执行操作。


2
请注意,如果文件末尾有任何空行,则此命令将发出警告。
通配符
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.