Vim пошук і заміна вибраного тексту


109

Скажімо, у нас є текст, і я входжу у візуальний режим і вибираю якийсь текст. Як швидко здійснити пошук виділеного тексту та замінити його чимось іншим?

Відповіді:


135

Спробуйте виконати наступне або вкладіть у своє .vimrc

vnoremap <C-r> "hy:%s/<C-r>h//gc<left><left><left>

Якщо натиснути ctrl+ rу візуальному режимі, вам буде запропоновано ввести текст для заміни. Натисніть enterта підтвердіть кожну зміну, з якою ви погоджуєтесь yабо відхиляєтесь n.

Ця команда замінить ваш реєстр, hщоб ви могли вибрати інший (змінивши hкоманду вище на іншу малу літеру), яку ви не використовуєте.


13
Якщо опустити cв систему gc, замінити робиться відразу у всьому буфері. Якщо ви допустили помилку і хочете її відновити, просто введіть uу командному режимі. Мені подобається такий підхід краще, ніж підтвердження кожної із замін (що відбувається з cмодифікатором).
Нілокт

3
vmap * y:let @/ = @"<CR>виділено виділено.
кев

8
Яка мета <left><left><left>?
aymericbeaumet

7
@aymericbeaumet, щоб отримати курсор між двома передніми косою рисою, таким чином слово заміни можна легко набрати.
mcabrams

5
Зауважте, що якщо ви скористаєтесь пропозицією @ Niloct про видалення cз gc, вам також доведеться видалити один із <left>кінців рядка.
Друг Натан

36

Цей швидкий і простий пошук для пошуку візуально виділеного тексту (без надмірного запису на h-регістр) і без використання терміналу, залежного від + реєстру:

" search for visually hightlighted text
vnoremap <c-f> y<ESC>/<c-r>"<CR>   

Якщо вам не подобається ctrl-f, змініть його на свої уподобання

Після виділення тексту ви завжди можете зробити sспрощення, просто ввівши:

%s//<your-replacement-string>

... тому що для пустого пошуку в sкоманді використовується останній шуканий рядок.


Коли я використовую це у своїй конфігурації vim, control+fзавжди вибирає наступний символ, а також те, що я обрав візуально. Якісь ідеї?
Роберт Марк Брам

%s//<your-replacement-string>схоже, не працює на виділення чогось подібного /tmp/file. це просто стає<your-replacement-string>/tmp/file
naisanza

28

Цей також працює (принаймні, для виділень у одному рядку / виділеннях, які не містять спеціальних символів)

  • виберіть текст у візуальному режимі
  • потягніть текст за допомогою y
  • :s/<C-r>0/

0 є реєстр янків.

Як згадували інші люди, є більш швидкі способи зробити це, але якщо ви тільки почали вивчати Vim (як я), це один із «загальних» способів.

// редагувати: Я щойно зрозумів, що підхід «зареєструватись» не вдасться, якщо /у виділенні є такі символи, як вкладки чи нові рядки чи символи (я повинен був би якось вручну обробити ці символи, щоб :sкоманда працювала):

введіть тут опис зображення


2
Це дуже просто. О Боже, чому це не висвітлено у вікі. Давай ... Дякую за відповідь!
Benyamin Limanto

2
Це ідеальна відповідь для тих із нас, хто ще перебуває на ранній частині кривої навчання Vim. Я знаю, що налаштування - це сила, але я не хочу копіювати і вставляти складний скрипт у свій vimrc та головоломку, як він підходить разом для такої простої проблеми. Ця відповідь навчила мене, що ctrl-R скидає реєстр, який буде зручно запам'ятати в інших контекстах.
nivek

26

Прийнята відповідь чудово працює, якщо у візуальному виборі у вас немає спеціальних символів. Я зламав два сценарії ( розміщений тут Джеремі Кантрелл та Пітер Оддінг ), щоб скласти команду, яка дозволить вам візуально вибрати рядок, який ви хочете знайти, навіть якщо в ньому є спеціальні символи регексу.

" Escape special characters in a string for exact matching.
" This is useful to copying strings from the file to the search tool
" Based on this - http://peterodding.com/code/vim/profile/autoload/xolox/escape.vim
function! EscapeString (string)
  let string=a:string
  " Escape regex characters
  let string = escape(string, '^$.*\/~[]')
  " Escape the line endings
  let string = substitute(string, '\n', '\\n', 'g')
  return string
endfunction

" Get the current visual block for search and replaces
" This function passed the visual block through a string escape function
" Based on this - /programming/676600/vim-replace-selected-text/677918#677918
function! GetVisual() range
  " Save the current register and clipboard
  let reg_save = getreg('"')
  let regtype_save = getregtype('"')
  let cb_save = &clipboard
  set clipboard&

  " Put the current visual selection in the " register
  normal! ""gvy
  let selection = getreg('"')

  " Put the saved registers and clipboards back
  call setreg('"', reg_save, regtype_save)
  let &clipboard = cb_save

  "Escape any special characters in the selection
  let escaped_selection = EscapeString(selection)

  return escaped_selection
endfunction

" Start the find and replace command across the entire file
vmap <leader>z <Esc>:%s/<c-r>=GetVisual()<cr>/

Я включив це до свого vimrc, якщо це корисніше для когось.


2
дякую за рішення, поєднуючи кілька пропозицій, я закінчив таке: vmap <C-r> <Esc>:%s/<c-r>=GetVisual()<cr>//g<left><left>(що просто замінює все у файлі)
Петро Буткович

13

З Vim 7.4 ви можете використовувати gnрух, який вибирає області тексту, які відповідають поточному шаблону пошуку.

Використовуючи cgnдля зміни тексту в обраному поточному збігу (або dgnдля видалення), у звичайному режимі ви можете .повторити команду та працювати над наступним збігом.

Існує епізод Vimcast, що показує цю особливість.


3
Це чудова відповідь!
mauriciojost

Це теж приголомшливо. осторонь відповіді на колемік. Чудовий!
Benyamin Limanto

уау, це як один із тих секретів, які ви знайдете, коли переглянете глибоко, щоб знайти гарне рішення, дякую!
vdegenne

8

Микола Голубєв, дякую за пораду! Далі використовується реєстр "+", який (залежно від вашого терміналу) вже містить виділений текст, рятуючи від використання регістру "h".

vnoremap <C-r> <Esc>:%s/<C-r>+//gc<left><left><left>

Мій VIM 7.0 на CentOS 5.x, схоже, не має регістру +. Це стандартна функція?
dotancohen

3
Зауважу, що я отримую доступ до машини CentOS через Putty, і після гугл я бачу, що + - це регістр буфера обміну. Мабуть, схоже, це не підтримує! Тож ця відповідь насправді залежить від терміналу.
dotancohen

Привіт, я спробував вашу команду, але вона просить мене замінити виникнення зазначеного тексту у всьому файлі, а не лише у вибраному тексті
solalito

7

З http://vim.wikia.com/wiki/Search_and_replace_in_a_visual_selection :

Коли текст візуально обраний, натисніть: щоб ввести команду. Командний рядок автоматично вводить діапазон:

:'<,'>

Ви можете ввести таку команду, як s / red / green / g, щоб замінити кожне червоне на зелене у всіх рядках останнього візуального вибору. Команда з’явиться у вигляді:

:'<,'>s/red/green/g

Щоб повторити команду Ex над попередньо вибраним блоком, використовуйте: history. Тобто натисніть: тоді, а потім відредагуйте попередню команду.


4
так, це замінює червоний на зелений у вибраній області - дуже корисно, але не те, про що звернувся до оператора.
ErichBSchulz

@ErichBSchulz Фактично це робить у всіх вибраних рядках. Отже, навіть якщо вибрана лише частина рядка, вона буде робити це для всього рядка.
Cully

1
Можливо, це не відповідає на питання ОП, але це точно відповідає моєму пошуку "vim пошук і заміна візуальним вибором", де я хочу обмежити пошук і замінити лише візуальний вибір, який викликає це питання
icc97

5

Я маю це у своєму vimrc:

function! GetVisual() range
    let reg_save = getreg('"')
    let regtype_save = getregtype('"')
    let cb_save = &clipboard
    set clipboard&
    normal! ""gvy
    let selection = getreg('"')
    call setreg('"', reg_save, regtype_save)
    let &clipboard = cb_save
    return selection
endfunction

vmap <leader>z :%s/<c-r>=GetVisual()<cr>/

Це захопить візуальний вибір і запустить команду заміни з ним.

EDIT: Я мушу зазначити, що це не працює з багатолінійними візуальними виділеннями. Хоча у GetVisual () немає проблем з поверненням, я не впевнений, як правильно розмістити його в командному рядку. Якщо хтось має поради, як я можу це зробити, будь ласка, прокоментуйте.


2

Я не думаю, що ти можеш це зробити поза межами. Але багатьом людям подобається ця функція, тому є багато макросів і подібних (я сам це додав). Ось такий, який ви можете додати, наприклад; просто натисніть, *щоб шукати наступний збіг у візуально вибраному тексті.


2

Інші відповіді хороші, але спеціальні символи не уникають. У відповіді @brian kennedy показаний спосіб втечі, але для цього потрібен великий код. Наприклад, у випадку URL-адреси, пропуск обов'язковий, або пошук припиниться на ":".

Як написано в vim.fandom.com/wiki/Search_for_visual_selected_text , ви можете зробити oneliner для пошуку та втечі деяких символів. Ви можете уникнути бажаних персонажів, я вибрав втечу /\: :

vnoremap // y/\V<C-R>=escape(@",'/\:')<CR><CR>

За допомогою цієї карти я повинен натиснути //у візуальному режимі, щоб шукати текст, який ви обрали в даний час, у всьому буфері.


1

Моя улюблена коротка версія цього

vnoremap s / y: s / "/

Потім ви можете виділити виділення та просто натиснути s /, щоб запустити команду заміни для нього.


Не працював для мене, трактувався "як буквальний. <c-r>"працював, хоча
Джош Бода

1

У мене немає коментаря, щоб коментувати, тому я додаю ще одну відповідь ...

vnoremap <C-r> "0y<Esc>:%s/<C-r>0//g<left><left>

@dmd та @dotancohen: це працювало для мене, не використовуючи "h(явно використовує 0, що все-таки є останньою позицією yank) і працює з putty ssh -> mint (lmde); не знаю про цент. Для видалення підтвердження також використовує коментарі @Niloct та @Nathan Friend.


1

Приклад 1. Котирування виділення зірочками, тримати курсор на початку вибору.

:%s,\%#\%V\_.*\%V/,**&**,c 

Приклад 2. Трубний вибраний текст із базою64:

:%s!\%#\%V\_.*\%V!\=system("base64 -w 0",@")!c

Пояснення LHS:

\%# matches cursor 
\%V matches inside the selection only
\_. matches any character.
\_.* matches beginning to end of selection.

Пояснення RHS:

\=expr()  Replace match with result of expr() for each substitution.

0

Я сподівався, що у Vim побудований спосіб замінити слово, не потрібно вводити слово в першу чергу. Є, хоча це буде працювати лише для тексту до граничного символу слова.

Після того, як ви переможете над словом, натисніть *або, #щоб виділити слово, і перейдіть до наступного / попереднього місця його розташування (якщо ви не хочете змінювати місця у файлі, натисніть протилежну клавішу, щоб повернутися до місця розташування ви були просто у).

Потім просто введіть:

%s//<your-replacement-string>

Як згадується у відповіді іншої людини, якщо %sміж косою рисою потрапляє порожній запис, то вона використовує раніше шукане слово. Натискаючи *або #, ви шукаєте слово під курсором, що робить його останнім пошуковим словом.

Зрештою, для цього потрібно лише шість-сім натискань клавіш + довжина слова, що заміняється, і для цього не потрібен макрос або редагування .vimrc.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.