考虑以下Vim ex命令,
:let i=1 | '<,'>g/^/ s/^\ *-/\=i/ | let i+=1
它用选定行中的有序数替换标题短划线。
我不明白为什么这个命令可以作为从所选行的第一行到最后一行的循环。也就是说,g
可以一遍又一遍地重复let i+=1
。
答案 0 :(得分:6)
全局命令的模式是:
:range g[lobal][!]/pattern/cmd
全局命令的工作方式是首先扫描线的[范围]并标记匹配发生的每一行。在第二次扫描中,对每个标记的行执行[cmd],其行号前置。如果更改或删除行,则其标记将消失。 [range]的默认值是整个文件。 (有关详细信息,请参阅http://vimregex.com/#global)
现在让我们分析一下
:let i=1 | '<,'>g/^/ s/^\ *-/\=i/ | let i+=1
一步一步。
let i=1
是执行的单个命令,用于设置循环的基本编号。我们可以在一开始就单独执行它。然后'<,'>g/^/ s/^\ *-/\=i/ | let i+=1
看起来更像是一个全局命令。'<,'>g
定义范围。 '<
代表第一行,'>
代表所选区域的最后一行。 (:help '<
了解更多详情)^
当然会匹配范围内的每一行。s/^\ *-/\=i/ | let i+=1
是[cmd],它执行的次数等于所选区域中的行数,这是循环发生的最重要原因。|
之前的部分是典型的替代命令:range s[ubstitute]/pattern/string/
(有关详细信息,请参阅http://vimregex.com/#substitute)^\ *-
匹配0个或更多的空格,后跟一行的开头。我们用\=i
代替这种模式。 (:help :s\=
了解更多详情)s/^\ *-/\=i/
后,执行let i+=1
。然后是下一行,......,直到所选区域的最后一行。s/^\ *-/\=i/ | let i+=1
是[cmd]整体,我们可以更改两个[sub-cmd]的顺序,获取let i+=1 | s/^\ *-/\=i/
。但是,同样的效果,let i=0
在一开始就是必不可少的。答案 1 :(得分:1)
这是:global
命令的一般模式:
:g/foo/command
因为第二个分隔符之后的所有内容都被视为一个命令,所以每次执行命令时计数器都会递增:每个匹配行一次。