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.
Greplace fonctionne bien pour moi.
Il y a aussi une version prête pour les pathogènes sur github.
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!
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)
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'
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 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 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/ .
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 rechercheqa
⇒ 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
: g
)c
)e
):cnf
⇒ passer au fichier suivant dans la liste créée par la commande vim
q
⇒ arrêter l'enregistrement de la macro1000@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
:args
à partir d'une commande ShellC'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
:args
de la liste des correctifsConsultez é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
, :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
où :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.
Encore une option en 2016, far.vim plugin:
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
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