在《Vim正则表达式》一书中,Oleg Raisky提供了以下命令以将多个空行减少为一个空白:
:g/^$/,/./-j
有人可以说明这是如何工作的吗?
我知道:g
命令和正则表达式。但我不明白该零件的/,/./-j
作用。
在《Vim正则表达式》一书中,Oleg Raisky提供了以下命令以将多个空行减少为一个空白:
:g/^$/,/./-j
有人可以说明这是如何工作的吗?
我知道:g
命令和正则表达式。但我不明白该零件的/,/./-j
作用。
Answers:
确实是很巧妙。让我们分解一下。该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
文档陈述了一种两遍算法,一种用于标记行,另一种用于执行操作。