在文章Vim Regular Expressions中,Oleg Raisky提供以下命令将多个空行减少为一个空白:
:g/^$/,/./-j
有人可以描述一下这是如何运作的吗?
我知道:g
命令和正则表达式。但我不明白/,/./-j
部分的作用。
答案 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文档说明了一个两遍算法,一个用于标记行,一个用于执行操作。
我可能在这一点上是错误的(这不是第一次),但它是一个不影响功能的实现细节。