在文章
Vim Regular Expressions中,Oleg Raisky提供了以下命令将多个空白行缩减为一个空白:
:g/^$/,/./-j
有人可以描述这是如何工作的吗?
我知道:g命令和正则表达式。但我不明白什么是/,/./-j的部分。
这真的很巧妙。让我们把它分解。 ex命令
g/^$/xyzzy
将搜索所有空行并对其中的每一个执行xyzzy命令(任意ex命令)。
这里棘手的是,xyzzy命令在你的情况下是另一个替代命令:
,/./-j
,/。/ – 指定范围。这是< start>,< end>并且,因为逗号之前没有任何东西,它假设当前行(您找到空行的那一行)是开始。
逗号之后是/./-,这意味着搜索下一个字符(。表示任何字符),然后备份一行(/./-是/./-1的缩写,因为如果没有给出值,则暗示该字符) 。你会发现这种模式。在您操作的第一个非空行上。
换句话说,范围的结束是您当前操作的最后一个空行。
然后在该范围内执行连接。
如果范围的开始和结束相等(在段中只有一个空行),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范围内的联接什么都不做。
对于第5行,/。/ – j将设置从5到8的范围(接下来,在行9上找到,然后减去1)。范围5,8上的连接将所有这些线连接在一起。
我不完全确定这一点,但我认为可能不会在作为早期操作的一部分消失的线上执行操作。这是因为处理在循环中被删除的行是没有意义的。
换句话说,由于第6行到第8行被删除(与第5行相结合),全局命令在这之后不对它们进行操作。我基于vim文档声明一个两遍算法,一个标记线,一个执行操作的事实。
我可能在这一点上错了(这不会是第一次),但它是一个实现细节,不影响功能。