Поиск и замена с добавочными значениями в Vim
Скажем, я написал простое правило CSS, подобное этому:
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
И мне нужно 10, поэтому я скопировал его 9 раз.
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
и др.
Теперь я хочу изменить star_10 и 0 0 с добавочными значениями, чтобы он выглядел так:
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
.star_9 {
background: url(stars.png) no-repeat 0 -18px;
}
.star_8 {
background: url(stars.png) no-repeat 0 -36px;
}
.star_7 {
background: url(stars.png) no-repeat 0 -54px;
}
и т.д.
Итак, как я могу искать/заменять каждый экземпляр, выполнять вычисления и записывать его?
Ответы
Ответ 1
Вы можете сделать это легко с помощью макроса. Допустим, у вас есть только это:
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
Наведите курсор на первую точку (в .star10
) и введите следующее в нормальном режиме:
qa3yy3jp^Xjt;18^Xk0q
Разъяснение:
-
qa
начнет запись макроса в регистре "a".
-
3yy
выдержит (скопирует) следующие 3 строки.
-
3j
поместит курсор на 3 строки вниз.
-
p
будет вставлять прошлый yanked текст.
-
^X
(ctrl + x) уменьшит номер класса звезды.
-
j
поместит курсор на одну строку вниз.
-
t;
поместит курсор перед следующей ;
в текущей строке.
-
18^X
уменьшит координату y фонового рисунка на 18;
-
k
поместит курсор в одну строку вверх,
-
0
поместит курсор в начало линии.
-
q
завершит запись макроса.
После этого у вас может быть что-то вроде этого.
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
.star_9 {
background: url(stars.png) no-repeat 0 -18;
}
Что это. Просто поместите курсор в точку на .star_9 и нажмите [email protected]
, чтобы выполнить макрос, записанный в регистре a
еще восемь раз.
Ответ 2
Вы можете использовать конструкцию s/pattern/replace
с символом \=
для оценки функции или выражения, как показано:
Уменьшение .star_10
:
let g:decr = 11
fu! Decr()
let g:decr = g:decr - 1
return g:decr
endfu
:%s/.star_10/\=".star_" . Decr()/
Аналогично, вы сделали бы
let g:decr_18 = 18
fu! Decr18()
let g:decr_18 = g:decr_18 - 18
return g:decr_18
endfu
а затем замените 0 0;
на
:%s/no-repeat 0 0;/\="no-repeat 0 " . Decr18() . "px"/
Для обеих функций объявляется (глобальная) переменная, которая обрабатывается внутри функций и возвращается. Сам функцин вызывается для каждой строки, соответствующей шаблону. шаблон заменяется выражением, следующим за \=
.
Ответ 3
Возможно, вы могли бы написать функцию для этого, но я обычно делаю что-то более простое. Я использую ключевой макрос, содержащий ключи ^ A и ^ X (увеличение и уменьшение числа). Используйте qa
, чтобы начать запись, делать свои вещи, используя эти клавиши с помощью модификаторов подсчета (например, 18^X
) и просто скажите, 10 @впоследствии.
Ответ 4
Мне нужно это решение, но также с поддержкой нулевого уровня. Мое использование исходного вопроса больше похоже на пример 1, чем на пример 2 (это был оригинальный пример).
Я создал функцию с именем SearchIncr() (search, replace, and increment)
.
Существует четыре требуемых аргумента: target_string
, replacement_string
, start_value
, increment_value
.
Существуют также два необязательных аргумента: leading_zeros
, position
leading_zeros
- положительное целочисленное значение, а position
- "до" или "после". См. Пример 2.
Пример 1
:'<,'>call SearchIncr("0 0","new",1,5,8)
Если файл выглядит так:
what 0 0 post
areu 0 0 post
doin 0 0 post
Затем вы получите:
what new00000001 post
areu new00000006 post
doin new00000011 post
Пример 2
:'<,'>call SearchIncr("0;","px;",-18,-18,0,'after')
Если файл выглядит так:
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
.star_10 {
background: url(stars.png) no-repeat 0 0;
}
Затем вы получите:
.star_10 {
background: url(stars.png) no-repeat 0 -18px;
}
.star_10 {
background: url(stars.png) no-repeat 0 -36px;
}
.star_10 {
background: url(stars.png) no-repeat 0 -54px;
}
Vimscript находится здесь:
" place functions here
function! SearchIncr(a1,a2,a3,a4,...)
" patn, repl, start, increment
let target = a:a1
let repl = a:a2
let startval = a:a3
let increment = a:a4
" 1st optional argument handles leading zeros
" process optional leading zero
if a:0 >= 1
let leadingz = a:1
else
" default to 0
let leadingz = 0
endif
" 2nd optional argument handles if target string goes before or after
" default is before
if a:0 == 2
" ideally set to 'after'
let repl_pos = a:2
else
let repl_pos = 'before'
endif
" inits
let l:incr = startval - increment
let lnum = a:firstline
" cycle though selection
while lnum <= a:lastline
" the FORMATTING string
if repl_pos == 'before'
let l:incrstring = '\=printf(''%s%0'. leadingz . 'd'',repl,l:incr)'
elseif repl_pos == 'after'
let l:incrstring = '\=printf(''%0'. leadingz . 'd%s'',l:incr,repl)'
else
"default to no leading zero and before placement
let l:incrstring = '\=printf(''%s%0d'',repl,l:incr)'
endif
" only increment counter when target matches
if match(getline(lnum),target) > 0
let l:incr = l:incr + increment
endif
" the search and replace
call setline(lnum,substitute(getline(lnum),target,
\ l:incrstring,'g'))
let lnum = lnum + 1
endwhile
endfunction
Любые комментарии для улучшения вышеизложенного были бы очень благодарны!