Rechercher et remplacer dans Vim dans tous les fichiers du projet

Je cherche le meilleur moyen d’effectuer une recherche et un remplacement (avec confirmation) sur tous les fichiers de projet dans Vim. Par “fichiers de projet”, j’entends les fichiers du répertoire en cours, dont certains ne doivent pas nécessairement être ouverts.

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

:args ./** 

puis effectuez la recherche et remplacez 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 aussi le plugin EasyGrep installé, mais ça ne marche presque jamais – soit il ne trouve pas toutes les occurrences, ou il se bloque jusqu’à ce que j’appuie sur Ctrl C. Jusqu’à présent, ma façon préférée d’accomplir cette tâche était d’ ack-grep pour le terme de recherche, en utilisant sa fenêtre quickfix, ouvrez tout fichier contenant le terme et n’a pas été ouvert auparavant, et enfin :bufdo %s/Search/Replace/gce .

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

Greplace fonctionne bien pour moi.

Il existe également une version prête pour les agents pathogènes sur github.

L’autre grande option est de ne pas utiliser vim:

 sed -i 's/pattern/replacement/'  

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!

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

 1. :grep  2. :cdo %s///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 remplit votre commande grep .)

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

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 que le sous-ensemble GNU.

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

Explication

ack

ack est un outil de ligne de commande impressionnant qui combine des expressions régulières grep , find et Perl complètes (pas seulement le sous-ensemble GNU). Il est écrit en pur Perl, sa rapidité, sa syntaxe de mise en évidence, fonctionne sous Windows et est 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 à modifier le fichier en place. Vous pouvez modifier cela pour créer des sauvegardes. L’option -E oblige Perl à exécuter la ligne de code spécifiée en tant que programme. Dans notre cas, le programme est juste 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/ .

Populate :args d’une commande shell

Il est possible (sur certains systèmes d’exploitation 1 ) de fournir les fichiers pour :args via une commande shell.

Par exemple, si ack 2 est installé,

 :args `ack -l pattern` 

demandera à ack de renvoyer une liste de fichiers contenant ‘pattern’ et de les placer dans la liste des arguments.

Ou avec plaine ol ‘grep 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 de correctifs

Consultez également la réponse de nelstrom à une question connexe décrivant une commande simple définie par l’utilisateur, qui remplit l’architecte de la liste de correctifs actuelle. Cela fonctionne très bien avec beaucoup de commandes et de plugins dont la sortie se retrouve dans la liste de correctifs ( :vimgrep :Ack 3 :Ggrep 4 ).

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 de la liste de correctifs.

Vous trouverez également dans la discussion qui suit des liens vers de simples plug-ins permettant d’obtenir ce stream de travail jusqu’à 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

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 ) pattern dans tous les fichiers de tous les sous-répertoires du cwd sans déclencher autocmds ( :noautocmd ), pour des raisons de rapidité.
  • :set hidden ⇒ permet 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 un registre a
  • :%s//Replace/gce ⇒ remplacer toutes les occurrences du dernier modèle de recherche (still /Search/ à ce moment-là) par Replace :
    • plusieurs fois sur une même ligne (drapeau g )
    • avec confirmation de l’utilisateur (indicateur c )
    • sans erreur si aucun motif n’a été trouvé ( e flag)
  • :cnf ⇒ passer au fichier suivant dans la liste créée par la commande vim
  • q ⇒ arrêter l’enregistrement macro
  • 1000@a ⇒ jouer la macro stockée dans le registre 1000 fois
  • :wa ⇒ enregistrer tous les tampons modifiés

* EDIT * Vim 8 façon:

À partir de Vim 8, il existe un meilleur moyen de le faire, comme :cfdo itère sur tous les fichiers de la liste de correctifs:

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

Si cela ne vous dérange pas d’introduire une dépendance externe, j’ai créé un plug-in ctrlsf.vim (dépendant de ack ou ag ) pour faire le travail.

Il peut formater et afficher les résultats de la recherche à partir de ack / ag et synchroniser vos modifications dans la mémoire tampon des résultats avec les fichiers réels sur le disque.

Peut-être que suite à la démo explique plus

ctrlsf_edit_demo

Une autre option en 2016, le plugin far.vim :

far.vom

Fondamentalement, je voulais le remplacer en une seule commande et, plus important encore, au sein même de vim

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

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

maintenant de la vim, sur un coup de chef + r je reçois la commande chargée dans vim, que j’édite comme ci-dessous,

 :!grep -r -l   | xargs sed -i -e 's///g' 

Par conséquent, je fais le remplacement par une seule commande et, plus important encore, au sein même de vim