Можно увеличить счетчик, используя замену с
особенность выражения (см. :help sub-replace-\=
). Поскольку конструкция \=
разрешает только выражения, команду :let
запрещено использовать, и
поэтому переменная не может быть установлена обычным способом. Тем не менее, есть
простой трюк, чтобы изменить значение переменной в выражении, если это
Переменная - это список или словарь. В этом случае его содержимое может быть
изменено функцией map()
. Таким образом, замена для случая
описанный в вопросе будет выглядеть следующим образом. 1
:let n=[0] | %s/Id="F"/\='Id="'.map(n,'v:val+1')[0].'"'/g
Или лучше, 2
:let n=[0] | %s/Id="\zsF\ze"/\=map(n,'v:val+1')/g
Этот короткий однострочник полностью решает проблему.
Для частых замен, таких как приведенная выше, можно определить вспомогательную
функция
function! Inc(x)
let a:x[0] += 1
return a:x[0]
endfunction
и сделать команды подстановки еще короче,
:%s/Id="\zsF\ze"/\=Inc(n)/g
1 Хитрая часть здесь находится в замещающей части
замена. Поскольку он начинается с \=
, остальная часть интерпретируется как
выражение от Vim. Таким образом, 'Id="'.map(n, 'v:val+1').'"'
является обычным
выражение. Здесь объединяется строковый литерал 'Id="'
(с использованием .
оператор) с возвращаемым значением вызова функции map(n, 'v:val+1')
, и с
другая строка, '"'
. Функция map
ожидает два аргумента: список (как в
в этом случае) или словарь, и строка, содержащая выражение, которое должно быть
оценивается для каждого из элементов в данном списке или словаре. Специальный
переменная v:val
обозначает отдельный элемент списка. Итак, строка 'v:val+1'
будет оцениваться как элемент списка, увеличенный на единицу.
2 Атомы паттернов \zs
и \ze
используются для установки начала и
конец шаблона для замены соответственно (см. :help /\zs
и :help
/\ze
). Таким образом, вся поисковая часть замещающей команды совпадает,
но заменяется только часть между \zs
и \ze
. Это позволяет избежать неуклюжий
конкатенации в выражении замены.