g如何在Vim ex命令脚本中循环
How g makes loop in Vim ex command script
考虑以下 Vim ex 命令,
:let i=1 | '<,'>g/^/ s/^\ *-/\=i/ | let i+=1
它用选定行中的有序数字替换标题破折号。
我不明白为什么这个命令从所选行的第一行到最后一行循环工作。也就是说,g
怎么会一遍又一遍地重复let i+=1
。
这是 :global
命令的一般模式:
:g/foo/command
因为第二个分隔符之后的所有内容都被视为一个命令,每次执行命令时计数器都会递增:每个匹配行一次。
全局命令的模式是:
:range g[lobal][!]/pattern/cmd
全局命令的工作方式是首先扫描行的 [range] 并标记出现匹配的每一行。在第二次扫描中,[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
是必不可少的。
考虑以下 Vim ex 命令,
:let i=1 | '<,'>g/^/ s/^\ *-/\=i/ | let i+=1
它用选定行中的有序数字替换标题破折号。
我不明白为什么这个命令从所选行的第一行到最后一行循环工作。也就是说,g
怎么会一遍又一遍地重复let i+=1
。
这是 :global
命令的一般模式:
:g/foo/command
因为第二个分隔符之后的所有内容都被视为一个命令,每次执行命令时计数器都会递增:每个匹配行一次。
全局命令的模式是:
:range g[lobal][!]/pattern/cmd
全局命令的工作方式是首先扫描行的 [range] 并标记出现匹配的每一行。在第二次扫描中,[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
是必不可少的。