Подтвердить что ты не робот

Поиск и замена с добавочными значениями в 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;
}

и т.д.

Итак, как я могу искать/заменять каждый экземпляр, выполнять вычисления и записывать его?

4b9b3361

Ответ 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

Любые комментарии для улучшения вышеизложенного были бы очень благодарны!