Когда я ищу с помощью команды /
нормального режима:
/\vSEARCHTERM
Vim начинает поиск с позиции курсора и продолжается вниз, возвращаясь к началу. Однако, когда я ищу и заменяю с помощью :substitute
команды:
:%s/\vBEFORE/AFTER/gc
Вместо этого Vim запускается с начала файла.
Есть ли способ заставить Vim выполнять поиск и замену, начиная с позиции курсора и переходя к началу, когда он достигает конца?
\vpattern
- «очень магический» шаблон: не буквенно-цифровые символы интерпретируются как специальные символы регулярного выражения (экранирование не требуется)%
? Я не вижу разумного смысла в том, что вы все равно просматриваете весь файл.Ответы:
1. Нетрудно добиться такого поведения с помощью двухэтапной замены:
Сначала выполняется команда подстановки для каждой строки, начиная с текущей и до конца файла:
Затем эта
:substitute
команда повторяется с тем же шаблоном поиска, строкой замены и флагами, используя:&
команду (см.:help :&
):Последний, однако, выполняет замену диапазона строк от первой строки файла до строки, в которой была установлена предыдущая метка контекста, минус один. Поскольку первая
:substitute
команда сохраняет позицию курсора до начала фактических замен, адресуемая строка''
- это строка, которая была текущей до того, как была запущена эта команда замены. (The''
адрес относится к'
псевдо-метке; см:help :range
и:help ''
для деталей.)Обратите внимание, что вторая команда (после
|
разделителя команд - см.:help :bar
) Не требует никаких изменений при изменении шаблона или флагов в первой.2. Чтобы сэкономить время на вводе текста, чтобы вызвать скелет вышеуказанной команды подстановки в командной строке, можно определить отображение в нормальном режиме, например:
Завершающая
<c-b><right><right><right><right>
часть необходима для перемещения курсора в начало командной строки (<c-b>
), а затем на четыре символа вправо (<right>
× 4), таким образом, помещая его между первыми двумя знаками косой черты, чтобы пользователь мог начать вводить шаблон поиска. . Когда желаемый узор и замена готовы, получившуюся команду можно запустить, нажав Enter.(Можно было бы подумать о том,
//
чтобы вместо///
приведенного выше сопоставления, если кто-то предпочитает вводить шаблон, затем введите разделяющую косую черту самостоятельно, за которой следует строка замены, вместо использования стрелки вправо для перемещения курсора над уже существующей разделяющей косой чертой, начиная с запасная часть.)источник
:noremap <leader>R :,$s///gc\|1,''-&&<c-b><right><right><right><right>
. Он помещается:,$s///gc|1,''-&&
в командную строку с курсором между первыми двумя знаками косой черты. После того, как вы введете желаемый узор и замену, вы можете запустить полученную команду, нажав Enter .Вы уже используете диапазон,
%
который является сокращением для1,$
обозначения всего файла. Чтобы перейти от текущей строки к концу, используйте.,$
. Точка означает текущую строку и$
означает последнюю строку. Итак, команда будет такой:Но
.
можно предположить, что текущая строка или может быть удалена:Для получения дополнительной помощи см.
источник
10:s/pattern/replace/gc
%
- это ярлык для1,$
(Vim help =>
:help :%
равно 1, $ (весь файл).).
это позиция курсора, поэтому вы можете сделатьЗаменить от начала документа до курсора
и т.д
Я настоятельно рекомендую вам прочитать руководство по диапазону, так
:help range
как практически все команды работают с диапазоном.источник
Я НАКОНЕЦ придумал решение того факта, что выход из поиска переносится в начало файла без написания огромной функции ...
Вы не поверите, сколько времени мне понадобилось, чтобы это придумать. Просто добавьте запрос, следует ли переносить: если пользователь
q
снова нажимает , не переносить. В общем, выйдите из поиска, нажавqq
вместоq
! (И если вы хотите обернуть, просто введитеy
.)Я действительно привязал это к горячей клавише. Так, например, если вы хотите найти и заменить каждое слово под курсором, начиная с текущей позиции, на
q*
:источник
q
,l
или Esc ) и не хотите продолжать с начала, вы уже можете снова нажатьq
или Esc, чтобы сразу выйти из второй команды. То есть предлагаемое добавление подсказки, похоже, эффективно дублирует уже существующую функциональность.yyyq
, продолжать редактирование без дезориентирующих скачков. Ноyyyqq
это почти так же хорошо, если вы рассматриваете двойное нажатие в значительной степени с точки зрения простоты использования.q
второго нажатия ). Последний оставляет курсор на последнем вхождении, которое было заменено (непосредственно передq
нажатием первого ).norm!``
команду::,$s/BEFORE/AFTER/gc|1,''-&&|norm!``
.Вот что-то очень грубое, что устраняет опасения по поводу обертывания поиска двухэтапным подходом (
:,$s/BEFORE/AFTER/gc|1,''-&&
) или промежуточным «Продолжить в начале файла?» подходить:Эта функция использует несколько приемов, чтобы проверить, следует ли нам переходить к началу:
источник
Я опаздываю на вечеринку, но я слишком часто полагался на таких запаздывающих ответчиков stackoverflow, чтобы этого не сделать. Я собрал подсказки по Reddit и stackoverflow, и лучший вариант - использовать
\%>...c
шаблон в поиске, который соответствует только после вашего курсора.Тем не менее, это также портит шаблон для следующего шага замены, и его трудно набрать. Чтобы противостоять этим эффектам, пользовательская функция должна впоследствии отфильтровать шаблон поиска, тем самым сбросив его. Увидеть ниже.
Я попытался использовать отображение, которое заменяет следующее вхождение и переходит к следующему после, но не более (в любом случае это была моя цель). Я уверен, что, опираясь на это, можно разработать глобальную замену. Имейте в виду, работая над решением, нацеленным на что-то подобное
:%s/.../.../g
, приведенный ниже шаблон отфильтровывает совпадения во всех строках, оставшихся до позиции курсора, но очищается после завершения одиночной замены, поэтому он теряет этот эффект сразу после этого, переходит к следующий матч и, таким образом, может проходить все совпадения один за другим.fun! g:CleanColFromPattern(prevPattern) return substitute(a:prevPattern, '\V\^\\%>\[0-9]\+c', '', '') endf nmap <F3>n m`:s/\%><C-r>=col(".")-1<CR>c<C-.r>=g:CleanColFromPattern(getreg("/"))<CR>/~/&<CR>:call setreg("/", g:CleanColFromPattern(getreg("/")))<CR>``n
источник