web-dev-qa-db-fra.com

Rechercher et remplacer dans Vim dans tous les fichiers de projet

Je cherche la meilleure façon de faire de la recherche et du remplacement (avec confirmation) dans tous les fichiers de projet dans Vim. Par "fichiers de projet", j'entends les fichiers du répertoire courant, dont certains n'ont pas besoin d'être ouverts.

Une façon de procéder pourrait être d'ouvrir simplement tous les fichiers du répertoire actuel:

:args ./**

puis faites la recherche et remplacez sur tous les fichiers ouverts:

:argdo %s/Search/Replace/gce

Cependant, lorsque je fais cela, l'utilisation de la mémoire de Vim passe de quelques dizaines de Mo à plus de 2 Go, ce qui ne fonctionne pas pour moi.

J'ai également le plugin EasyGrep installé, mais cela ne fonctionne presque jamais - soit il ne trouve pas toutes les occurrences, soit il se bloque jusqu'à ce que j'appuie sur CtrlC. Jusqu'à présent, ma façon préférée d'accomplir cette tâche consiste à ack-grep pour le terme de recherche, en utilisant sa fenêtre de correction rapide, ouvrez n'importe quel fichier qui contient le terme et n'a pas été ouvert auparavant, et enfin :bufdo %s/Search/Replace/gce.

Je recherche soit un bon plugin fonctionnel qui peut être utilisé pour cela, soit une commande/séquence de commandes qui serait plus facile que celle que j'utilise maintenant.

109
psyho

Greplace fonctionne bien pour moi.

Il y a aussi une version prête pour les pathogènes sur github.

26
tuxcanfly

L'autre grande option ici est simplement de ne pas utiliser vim:

sed -i 's/pattern/replacement/' <files>

ou si vous avez un moyen de générer une liste de fichiers, peut-être quelque chose comme ceci:

find . -name *.cpp | xargs sed -i 's/pattern/replacement/'
grep -rl 'pattern1' | xargs sed -i 's/pattern2/replacement/'

etc!

94
Cascabel

Grâce à la commande récemment ajoutée cdo , vous pouvez maintenant le faire en deux commandes simples en utilisant l'outil grep que vous ont installé. Aucun plugin supplémentaire requis!:

1. :grep <search term>
2. :cdo %s/<search term>/<replace term>/gc
3. (If you want to save the changes in all files) :cdo update

(cdo exécute la commande donnée à chaque terme de la liste de correctifs, que votre commande grep remplit.)

(Supprimez le c à la fin de la 2e commande si vous souhaitez remplacer chaque terme de recherche sans confirmer à chaque fois)

54
Sid

J'ai décidé d'utiliser ack et Perl pour résoudre ce problème afin de tirer parti des expressions régulières complètes Perl plus puissantes plutôt que du sous-ensemble GNU.

ack -l 'pattern' | xargs Perl -pi -E 's/pattern/replacement/g'

Explication

ack

ack est un outil de ligne de commande génial qui est un mélange d'expressions régulières grep, find et Perl complet (pas seulement le sous-ensemble GNU). Son écrit en pur Perl, son rapide, il a la coloration syntaxique, fonctionne sur Windows et son plus convivial pour les programmeurs que les outils de ligne de commande traditionnels. Installez-le sur Ubuntu avec Sudo apt-get install ack-grep.

xargs

Xargs est un ancien outil de ligne de commande Unix. Il lit les éléments de l'entrée standard et exécute la commande spécifiée suivie des éléments lus pour l'entrée standard. Donc, fondamentalement, la liste des fichiers générés par ack est ajoutée à la fin de la commande Perl -pi -E 's/pattern/replacemnt/g'.

Perl -pi

Perl est un langage de programmation. L'option -p oblige Perl à créer une boucle autour de votre programme qui itère sur les arguments de nom de fichier. L'option -i oblige Perl à éditer le fichier sur place. Vous pouvez le modifier pour créer des sauvegardes. L'option -E oblige Perl à exécuter la seule ligne de code spécifiée comme programme. Dans notre cas, le programme n'est qu'une substitution de regex Perl. Pour plus d'informations sur les options de ligne de commande Perl perldoc perlrun . Pour plus d'informations sur Perl, voir http://www.Perl.org/ .

34
Eric Johnson

peut-être faire ceci:

:noautocmd vim /Search/ **/*
:set hidden
:cfirst
qa
:%s//Replace/gce
:cnf
q
1000@a
:wa

Explication:

  • :noautocmd vim /Search/ **/* ⇒ lookup (vim est une abréviation de vimgrep) dans tous les fichiers de tous les sous-répertoires du cwd sans déclencher les autocmds (:noautocmd), pour la vitesse.
  • :set hidden ⇒ permettre d'avoir des tampons modifiés non affichés dans une fenêtre (pourrait être dans votre vimrc)
  • :cfirst ⇒ passer au premier résultat de recherche
  • qa ⇒ commencer à enregistrer une macro dans le registre a
  • :%s//Replace/gce ⇒ remplacer toutes les occurrences du dernier motif de recherche (toujours /Search/ à ce moment-là) avec Replace:
    • plusieurs fois sur une même ligne (drapeau g)
    • avec confirmation de l'utilisateur (drapeau c)
    • sans erreur si aucun modèle trouvé (drapeau e)
  • :cnf ⇒ passer au fichier suivant dans la liste créée par la commande vim
  • q ⇒ arrêter l'enregistrement de la macro
  • 1000@a ⇒ lire la macro stockée dans le registre 1000 fois
  • :wa ⇒ enregistrer tous les tampons modifiés

* EDIT * Vim 8 voies:

À partir de Vim 8, il existe une meilleure façon de le faire, comme :cfdo itère sur tous les fichiers de la liste des correctifs:

:noautocmd vim /Search/ **/*
:set hidden
:cfdo %s//Replace/gce
:wa
22
Benoit

Remplir :args à partir d'une commande Shell

C'est possible (sur certains systèmes d'exploitation1)) pour fournir les fichiers pour :args via une commande Shell.

Par exemple, si vous avez un accusé de réception2 installée,

:args `ack -l pattern`

demandera à ack de retourner une liste de fichiers contenant 'pattern' et les mettra sur la liste des arguments.

Ou avec du grep ordinaire, je suppose que ce serait:

:args `grep -lr pattern .`  


Vous pouvez alors simplement utiliser :argdo comme décrit par l'OP:

:argdo %s/pattern/replacement/gce


Remplir :args de la liste des correctifs

Consultez également réponse de nelstrom à une question connexe décrivant une commande définie par l'utilisateur simple qui remplit l'arglist à partir de la liste actuelle de correctifs. Cela fonctionne très bien avec de nombreuses commandes et plugins dont la sortie se retrouve dans la liste des correctifs (:vimgrep, :Ack3, :Ggrep4).

La séquence pour effectuer une recherche à l'échelle du projet pourrait alors être effectuée avec:

:vimgrep /pattern/ **/*
:Qargs 
:argdo %s/findme/replacement/gc

:Qargs est l'appel à la commande définie par l'utilisateur qui remplit l'arglist à partir de la liste des correctifs.

Vous trouverez également des liens dans la discussion qui suit vers des plugins simples qui réduisent ce flux de travail à 2 ou 3 commandes.

Liens

  1. : h {arglist} - vimdoc.sourceforge.net/htmldoc/editing.html#{arglist}
  2. ack - betterthangrep.com/
  3. ack.vim - github.com/mileszs/ack.vim
  4. fugitif - github.com/tpope/vim-fugitive
21
exbinary

Encore une option en 2016, far.vim plugin:

far.vom

7
Oleg Khalidov

Si cela ne vous dérange pas d'introduire une dépendance externe, j'ai créé un plugin ctrlsf.vim (dépend de ack ou ag ) pour faire le emploi.

Il peut formater et afficher les résultats de la recherche depuis ack/ag, et synchroniser vos modifications dans le tampon de résultats avec les fichiers réels sur le disque.

Peut-être que la démo suivante explique plus

ctrlsf_edit_demo

5
dyng

Fondamentalement, je voulais le remplacer en une seule commande et surtout au sein de vim lui-même

Sur la base du réponse de @Jefromi j'ai créé un raccourci clavier, que j'avais défini dans mon fichier .vimrc comme celui-ci

nmap <leader>r :!grep -r -l  * \| xargs sed -i -e 's///g'

maintenant depuis le vim, sur un coup de leader + r je reçois la commande chargée dans vim, que je modifie comme ci-dessous,

:!grep -r -l <find> <file pattern> | xargs sed -i -e 's/<find>/<replace>/g'

Par conséquent, je fais le remplacement par une seule commande et surtout dans vim lui-même

0
deepak