Vim: глобальный поиск и замена, начиная с позиции курсора
Когда я выполняю поиск с помощью
/\vSEARCHTERM
Vim начинает поиск с позиции курсора вниз, и он будет перемещаться вверх. Однако при поиске и замене с помощью
:%s/\vBEFORE/AFTER/gc
Vim начинается в верхней части файла.
Есть ли способ сделать поиск и замену Vim, начиная с позиции курсора И обертывая его вверх, как только он достигнет конца?
Ответы
Ответ 1
Нетрудно добиться такого поведения, используя двухэтапную замену:
:,$s/BEFORE/AFTER/gc|1,''-&&
Сначала выполняется команда подстановки для каждой строки, начиная с
текущий до конца файла. Затем команда :substitute
повторяется с тем же шаблоном поиска, заменой строки и флагов,
используя команду :&
. Последнее, однако, выполняет замену
в диапазоне строк от первой строки файла до строки, где
предыдущая метка контекста была установлена, минус одна. Начиная с первого
Команда :substitute
сохраняет позицию курсора перед началом фактического
замены, строка, адресованная ''
, - это строка, которая была
текущий до того, как была выполнена эта команда подстановки.
Обратите внимание, что вторая команда (после символа |
) не требует
изменение при изменении шаблона или флагов первого.
Ответ 2
Вы уже используете диапазон, %
, который является короткой рукой для 1,$
, что означает весь файл. Чтобы перейти от текущей строки до конца, вы используете .,$
. Период означает текущую строку, а $
означает последнюю строку. Таким образом, команда будет:
:.,$s/\vBEFORE/AFTER/gc
Но можно предположить, что .
или текущая строка могут быть удалены:
:,$s/\vBEFORE/AFTER/gc
Подробнее см.
:h range
Ответ 3
%
является ярлыком для 1,$
(Vim help = > :help :%
, равный 1, $(весь файл).)
.
- позиция курсора, поэтому вы можете сделать
:.,$s/\vBEFORE/AFTER/gc
Для замены с начала документа до курсора
:1,.s/\vBEFORE/AFTER/gc
и т.д.
Я настоятельно рекомендую вам прочитать руководство о диапазоне :help range
, так как почти все команды работают с диапазоном.
Ответ 4
Я НАКОНЕЦ придумал решение о том, что выход из поиска завершается в начале файла без написания огромной функции...
Ты не поверишь, как долго мне понадобилось это делать. Просто добавьте подсказку, следует ли обертывать: если пользователь снова нажимает q
, не обертывайте. Итак, в основном, прекратите поиск, нажав qq
вместо q
! (И если вы хотите обернуть, просто введите y
.)
:,$s/BEFORE/AFTER/gce|echo 'Continue at beginning of file? (y/q)'|if getchar()!=113|1,''-&&|en
На самом деле это сопоставляется с горячей клавишей. Например, если вы хотите искать и заменять каждое слово под курсором, начиная с текущей позиции, с помощью q*
:
exe 'nno q* :,$s/\<<c-r>=expand("<cword>")<cr>\>//gce\|echo "Continue at beginning of file? (y/q)"\|if getchar()==121\|1,''''-&&\|en'.repeat('<left>',77)
Ответ 5
Здесь что-то очень грубое, что касается проблем вокруг обхода поиска с помощью двухэтапного подхода (:,$s/BEFORE/AFTER/gc|1,''-&&
) или с промежуточным "Продолжить в начале файла?" :
" Define a mapping that calls a command.
nnoremap <Leader>e :Substitute/\v<<C-R>=expand('<cword>')<CR>>//<Left>
" And that command calls a script-local function.
command! -nargs=1 Substitute call s:Substitute(<q-args>)
function! s:Substitute(patterns)
if getregtype('s') != ''
let l:register=getreg('s')
endif
normal! qs
redir => l:replacements
try
execute ',$s' . a:patterns . 'gce#'
catch /^Vim:Interrupt$/
return
finally
normal! q
let l:transcript=getreg('s')
if exists('l:register')
call setreg('s', l:register)
endif
endtry
redir END
if len(l:replacements) > 0
" At least one instance of pattern was found.
let l:last=strpart(l:transcript, len(l:transcript) - 1)
" Note: type the literal <Esc> (^[) here with <C-v><Esc>:
if l:last ==# 'l' || l:last ==# 'q' || l:last ==# '^['
" User bailed.
return
endif
endif
" Loop around to top of file and continue.
" Avoid unwanted "Backwards range given, OK to swap (y/n)?" messages.
if line("''") > 1
1,''-&&"
endif
endfunction
Эта функция использует пару хаков, чтобы проверить, следует ли обтекать верх:
- Нет обертывания, если пользователь нажал "l", "q" или "Esc", любой из которых указывает на желание прервать.
- Обнаружение последнего нажатия клавиши путем записи макроса в регистр "s" и проверки его последнего символа.
- Избегайте перезаписи существующего макроса, сохраняя/восстанавливая регистр "s".
- Если вы уже записываете макрос при использовании команды, все ставки отключены.
- Пытается делать правильные действия с прерываниями.
- Предотвращает предупреждения "назад диапазона" с явным контролем.