Vim recherche et remplace le texte sélectionné

109

Disons que nous avons un texte, et j'entre en mode visuel et sélectionne du texte. Comment rechercher rapidement le texte en surbrillance et le remplacer par autre chose?

Gabriel Salomon
la source

Réponses:

135

Essayez d'exécuter ce qui suit ou insérez-le dans votre .vimrc

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

En appuyant sur ctrl+ ren mode visuel, vous serez invité à entrer le texte à remplacer par. Appuyez sur enterpuis confirmez chaque modification avec laquelle vous êtes d'accord you avec laquelle vous refusez n.

Cette commande remplacera votre registre hafin que vous puissiez en choisir un autre (en remplaçant hla commande ci-dessus par une autre lettre minuscule) que vous n'utilisez pas.

Mykola Golubyev
la source
13
Si vous omettez le cin gc, le remplacement est effectué en une seule fois dans tout le tampon. Si vous avez fait une erreur et que vous souhaitez la rétablir, tapez simplement uen mode commande. J'aime mieux cette approche que de confirmer chacun des remplacements (cela se produit avec le cmodificateur).
Niloct
3
vmap * y:let @/ = @"<CR>sélectionné est mis en surbrillance.
kev
8
Quel est le but <left><left><left>?
aymericbeaumet
7
@aymericbeaumet pour placer le curseur entre les deux barres obliques, de cette façon le mot de remplacement peut être facilement tapé.
mcabrams
5
Notez que si vous prenez la suggestion de @ Niloct sur la suppression du cde gc, vous devrez également supprimer l'un des <left>'s de la fin de la ligne.
Nathan Friend
36

Cette cartographie rapide et simple recherche le texte mis en évidence visuellement (sans écraser le registre h) et sans utiliser le registre + dépendant du terminal:

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

Si vous n'aimez pas le ctrl-f, changez-le selon vos préférences

Une fois le texte en surbrillance, vous pouvez toujours faire une substitution en tapant simplement:

%s//<your-replacement-string>

... car une recherche vide sur la scommande utilise la dernière chaîne recherchée.

ErichBSchulz
la source
Lorsque j'utilise cela dans ma configuration vim, control+fsélectionne toujours le caractère suivant ainsi que ce que j'ai sélectionné visuellement. Des idées?
Robert Mark Bram
%s//<your-replacement-string>ne semble pas fonctionner pour mettre en évidence quelque chose comme /tmp/file. il devient juste<your-replacement-string>/tmp/file
naisanza
29

Celui-ci fonctionne également (au moins pour les sélections sur une seule ligne / les sélections qui ne contiennent aucun caractère spécial)

  • sélectionnez le texte en mode visuel
  • tirez le texte avec y
  • :s/<C-r>0/

0 est le registre yank.

Comme d'autres personnes l'ont mentionné, il existe des moyens plus rapides de le faire, mais si vous venez de commencer à apprendre Vim (comme moi), c'est l'un des moyens «génériques».

// edit: Je viens de réaliser que l'approche 'register' échouera s'il y a des caractères comme des tabulations ou des retours à la ligne ou des /caractères dans la sélection (je devrais traiter manuellement ces caractères d'une manière ou d'une autre pour que la :scommande fonctionne):

entrez la description de l'image ici

colemik
la source
2
C'est très simple. Oh mon Dieu, pourquoi ce n'est pas couvert sur le wiki. Allez ... Merci pour la réponse!
Benyamin Limanto le
2
C'est la réponse idéale pour ceux d'entre nous qui sont encore au début de la courbe d'apprentissage de Vim. Je sais que la personnalisation est une force, mais je ne veux pas copier-coller un script complexe dans mon vimrc et comprendre comment il s'articule pour un problème aussi simple que celui-ci. Cette réponse m'a appris que ctrl-R vidait un registre, ce qui sera pratique à retenir dans d'autres contextes.
nivek le
26

La réponse acceptée fonctionne très bien, sauf si vous avez des caractères spéciaux dans votre sélection visuelle. J'ai piraté ensemble deux scripts (ceux de Jeremy Cantrell et de Peter Odding ) pour créer une commande qui vous permettra de sélectionner visuellement une chaîne que vous voulez trouver même si elle contient des caractères regex spéciaux.

" 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>/

J'ai inclus ceci dans mon vimrc si cela est plus utile à quiconque.

Bryan Kennedy
la source
2
merci pour la solution, combinant plusieurs propositions, je me suis retrouvé avec ce qui suit: vmap <C-r> <Esc>:%s/<c-r>=GetVisual()<cr>//g<left><left>(qui remplace simplement tout dans le fichier)
Peter Butkovic
13

À partir de Vim 7.4, vous pouvez utiliser le gnmouvement qui sélectionne les régions de texte qui correspondent au modèle de recherche actuel.

Après avoir utilisé cgnpour modifier le texte dans la correspondance actuellement sélectionnée (ou dgnpour supprimer), en mode normal, vous pouvez utiliser .pour répéter la commande et effectuer la correspondance suivante.

Il y a un épisode de Vimcast montrant cette fonctionnalité.

Dapeng Li
la source
3
C'est une excellente réponse!
mauriciojost
C'est aussi génial. à part la réponse colemik. Elle est bonne!
Benyamin Limanto le
wow, c'est comme l'un de ces secrets que vous trouvez lorsque vous parcourez profondément pour trouver une bonne solution, merci!
vdegenne
8

Mykola Golubyev, Merci pour la pointe! La suite utilise le registre "+" qui (selon votre terminal) contient déjà le texte en surbrillance, évitant ainsi l'utilisation du registre "h".

vnoremap <C-r> <Esc>:%s/<C-r>+//gc<left><left><left>
dmd
la source
Mon VIM 7.0 sur CentOS 5.x ne semble pas avoir le registre +. Est-ce une fonctionnalité standard?
dotancohen
3
Je note que j'accède à la machine CentOS via Putty, et en googlant je vois que + est le registre du presse-papiers. Putty ne semble pas soutenir cela! Donc, cette réponse dépend en fait du terminal.
dotancohen
Salut, j'ai essayé votre commande mais elle me demande de remplacer les occurrences du texte spécifié dans tout le fichier, et pas seulement le texte sélectionné
solalito
7

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

Lorsque le texte est sélectionné visuellement, appuyez sur: pour entrer une commande. La ligne de commande entrera automatiquement dans la plage:

:'<,'>

Vous pouvez entrer une commande telle que s / rouge / vert / g pour remplacer chaque rouge par du vert dans toutes les lignes de la dernière sélection visuelle. La commande apparaîtra comme:

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

Pour répéter une commande Ex sur un bloc précédemment sélectionné, utilisez: historique. Autrement dit, appuyez sur: puis, puis modifiez une commande précédente.

syvex
la source
4
oui, cela remplace le rouge par le vert dans la zone sélectionnée - très utile, mais pas ce que l'op a demandé.
ErichBSchulz
@ErichBSchulz Il le fait réellement sur toutes les lignes sélectionnées. Ainsi, même si seule une partie d'une ligne est sélectionnée, il le fera sur toute la ligne.
Cully
1
Peut-être que cela ne répond pas à la question OP, mais cela répond exactement à ma recherche "vim search and replace with visual selection", où je veux limiter la recherche et remplacer uniquement la sélection visuelle, ce qui soulève cette question
icc97
5

J'ai ceci dans mon 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>/

Cela saisira la sélection visuelle et lancera une commande de substitution avec elle.

EDIT: Je dois souligner que cela ne fonctionne pas avec les sélections visuelles multilignes. Bien que GetVisual () n'ait pas de problème à le renvoyer, je ne sais pas comment le mettre correctement dans la ligne de commande. Si quelqu'un a des conseils sur la façon dont je pourrais faire cela, veuillez commenter.

Jeremy Cantrell
la source
2

Je ne pense pas que vous puissiez faire ça hors de la boîte. Mais beaucoup de gens aiment cette fonctionnalité, donc il y a des tonnes de macros et autres (je l'ai ajoutée moi-même). En voici un que vous pouvez ajouter, par exemple; appuyez simplement sur *pour rechercher la correspondance suivante sur le texte sélectionné visuellement.

John Feminella
la source
2

D'autres réponses sont bonnes mais elles n'échappent pas aux caractères spéciaux. La réponse de @brian kennedy montre une méthode pour s'échapper mais cela nécessite beaucoup de code. Dans le cas d'une URL par exemple, l'échappement est obligatoire ou la recherche s'arrêtera sur «:».

Comme écrit dans vim.fandom.com/wiki/Search_for_visually_selected_text , vous pouvez faire un oneliner pour rechercher et échapper certains caractères. Vous pouvez échapper aux personnages que vous voulez, j'ai choisi de m'échapper /\: :

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

Avec cette carte, je dois appuyer sur //en mode visuel pour rechercher le texte actuellement sélectionné sur l'ensemble du tampon.

RomainTT
la source
1

Ma version courte préférée de ceci est

vnoremap s / y: s / "/

Ensuite, vous pouvez mettre en évidence une sélection et appuyez simplement sur s / pour lancer une commande de substitution.

Alex
la source
Cela n'a pas fonctionné pour moi, traité "comme un littéral. <c-r>"bien travaillé
Josh Bodah
1

Je n'ai pas le représentant à commenter, alors j'ajoute encore une autre réponse ...

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

@dmd et @dotancohen: cela a fonctionné pour moi sans épuiser "h(utilise explicitement 0, qui est de toute façon la dernière position de tirage) et fonctionne avec putty ssh -> mint (lmde); ne sais pas pour cent. Utilise également les commentaires @Niloct et @Nathan Friend pour supprimer la confirmation.

10'004
la source
1

Exemple 1. Citez la sélection avec des étoiles, gardez le curseur au début de la sélection.

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

Exemple 2. Pipe le texte sélectionné avec base64:

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

Explication LHS:

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

Explication RHS:

\=expr()  Replace match with result of expr() for each substitution.
mosh
la source
0

J'espérais qu'il y avait un moyen intégré dans Vim pour remplacer un mot, sans avoir à retaper le mot en premier lieu. Il y en a, bien que cela ne fonctionnera que pour le texte jusqu'à un caractère de limite de mot.

Une fois que vous avez survolé le mot, appuyez sur *ou #pour mettre le mot en surbrillance et passez à l'emplacement suivant / précédent (si vous ne voulez pas changer d'emplacement dans le fichier, appuyez sur la touche opposée pour revenir à l'emplacement vous étiez juste à).

Ensuite, tapez simplement:

%s//<your-replacement-string>

Comme mentionné dans la réponse d'une autre personne, si %sreçoit une entrée vide entre les barres obliques, alors il utilise le mot recherché précédemment. En appuyant sur *ou #, vous recherchez le mot sous le curseur, ce qui en fait le mot le plus récemment recherché.

En fin de compte, ce n'est que six ou sept frappes + longueur du mot de remplacement pour effectuer cela et cela ne nécessite aucune macro ou modification de votre .vimrc.

Cameron Gagnon
la source