Consider the following Vim ex command,
:let i=1 | \'<,\'>g/^/ s/^\\ *-/\\=i/ | let i+=1
It replaces the heading dash with ordered number
This is the general pattern of a :global
command:
:g/foo/command
Because everything after the second separator is considered as one command, the counter is incremented each time the command is executed: one time for each matching line.
The pattern of a global command is:
:range g[lobal][!]/pattern/cmd
The global commands work by first scanning through the [range] of of the lines and marking each line where a match occurs. In a second scan the [cmd] is executed for each marked line with its line number prepended. If a line is changed or deleted its mark disappears. The default for the [range] is the whole file. (see http://vimregex.com/#global for more details)
Now let's analyse
:let i=1 | '<,'>g/^/ s/^\ *-/\=i/ | let i+=1
step by step.
let i=1
is a single command executed setting the basic number for the loop. We can just execute it alone at the very beginning. Then '<,'>g/^/ s/^\ *-/\=i/ | let i+=1
looks a little more like a global command.'<,'>g
defines the range. '<
represents the first line and '>
represents the last line of the selected area. (:help '<
for more details)^
of course matches every line in range.s/^\ *-/\=i/ | let i+=1
is the [cmd], the number of times it will be executed equals to the number of lines in the selected area, and this is the most important reason why the loop took place.|
is a typical substitute command :range s[ubstitute]/pattern/string/
(see http://vimregex.com/#substitute for more details)^\ *-
matches 0 or more whitespace followed by a dash at the beginning of a line. We substitute \=i
for this pattern. (:help :s\=
for more details)s/^\ *-/\=i/
, let i+=1
is executed. Then the next line, ... , till the last line of selected area.s/^\ *-/\=i/ | let i+=1
is a [cmd] as a whole, we can change the order of the two [sub-cmd], obtaining let i+=1 | s/^\ *-/\=i/
. But for the same effect, let i=0
at the very beginning is essential.