Utiliser Emacs pour rechercher et remplacer de façon récursive dans les fichiers texte qui ne sont pas déjà ouverts
comme suite à cette question , c'est essayer de savoir comment faire quelque chose comme ça qui devrait être facile, qui m'empêche surtout de m'habituer à utiliser Emacs et à la place de démarrer L'éditeur que je connais déjà. J'utilise cet exemple assez souvent pour éditer plusieurs fichiers.
dans Ultraedit je ferais Alt+S puis p pour afficher une boîte de dialogue avec les options: Find (inclut l'utilisation d'expressions régulières à travers plusieurs lines), remplacer par, dans les fichiers / Types, répertoire, case de correspondance, Match mot entier seulement, Liste des fichiers modifiés et sous-répertoires de recherche. Habituellement, je vais d'abord utiliser la souris pour cliquer-glisser sélectionnez le texte que je veux remplacer.
utilisant seulement Emacs lui-même (sur Windows XP), sans appeler aucun utilitaire externe, comment remplacer tous foonbar avec barnbaz dans *.c
et *.h
fichiers dans un dossier et tous les dossiers sous elle. Peut-être Emacs n'est pas le meilleur outil pour ce faire avec, mais comment peut-il être fait facilement avec un minimum de commande?
13 réponses
-
M-x find-name-dired
: vous serez invité pour un répertoire racine et un motif de nom de fichier. - Appuyez sur
t
pour "changer de marque" pour tous les fichiers trouvés. - Appuyez sur
Q
pour "Query-replace dans les Fichiers...": vous serez invité pour requête / regexps de substitution. - procéder comme avec
query-replace-regexp
:SPACE
pour remplacer et passer au match suivant,n
pour sauter un match, etc. - appuyez sur
C-x s
pour sauvegarder les tampons. (Vous pouvez ensuite appuyer sury
,n
ou!
pour tout sauvegarder en une seule fois)
-
M-x find-name-dired RET
- il se peut qu'il faille un certain temps pour que tous les fichiers apparaissent dans la liste, faites défiler vers le bas (
M->
) jusqu'à ce que "find finished
"apparaisse pour s'assurer qu'ils ont tous chargé
- il se peut qu'il faille un certain temps pour que tous les fichiers apparaissent dans la liste, faites défiler vers le bas (
- Appuyez sur
t
à "basculer" tous les fichiers - Appuyez sur
Q
pour "Query-replace dans les Fichiers...": vous serez invité pour requête / regexps de substitution. - procéder comme avec query-replace-regexp: SPACE ou
y
pour remplacer et passer à la correspondance suivante, n pour sauter une correspondance, etc.- Type ! pour remplacer tous les événements dans le fichier courant sans demander,
N
pour sauter tous les remplacements possibles pour le reste du fichier courant. (N
est emacs 23+ uniquement) - pour effectuer le remplacement sur tous les fichiers sans autre demande, tapez
Y
.
- Type ! pour remplacer tous les événements dans le fichier courant sans demander,
- appeler "ibuffer" (
C-x C-b
si lié à ibuffer, ouM-x ibuffer RET
) pour lister tous les fichiers ouverts. - Type
* u
pour marquer tous les fichiers non enregistrés, de typeS
pour enregistrer tous les fichiers marqués -
* * RET
pour marquer toutes les marques, ou tapezD
pour fermer tous les fichiers marqués
cette réponse est combinée de cette réponse , de ce site , et de mes propres notes. En Utilisant Emacs 23+.
j'utilise généralement d'autres outils pour effectuer cette tâche, et il semble que beaucoup des approches mentionnées à Emacswiki trouver et remplacer à travers l'entrée de fichiers shell out, mais le paquet Findr semble très prometteur.
Voler une partie de la source du fichier :
(defun findr-query-replace (from to name dir)
"Do `query-replace-regexp' of FROM with TO, on each file found by findr.
Les réponses fournies sont grands, mais je pensais que je voudrais ajouter une approche légèrement différente.
c'est une méthode plus interactive, et nécessite wgrep
, rgrep
et iedit
. Les deux iedit
et wgrep
doivent être installés par MELPA ou marmelade (en utilisant M-x package-list-packages
)
Première M-x rgrep
pour rechercher la chaîne que vous recherchez.
vous serez en mesure de spécifier les types de fichiers/pattern et le dossier de manière récursive.
ensuite, vous devrez exécuter wgrep
démarrer avec C-s C-p
.
Wgrep vous permettra d'éditer les résultats rgrep
, donc définissez une région sur la chaîne de caractères pour faire correspondre et démarrer iedit-mode
avec C-;
(selon votre terminal, vous pourriez avoir besoin de re-lier cela)
tous les événements seront modifiables en une seule fois. "1519120920 de" commettre wgrep
. Puis C-x s !
pour sauver le modifié fichier.
Le principal avantage de cette méthode est que vous pouvez utiliser iedit-mode
pour désactiver certains matchs M-;
. Vous pouvez également utiliser les résultats dans rgrep
pour sauter dans les fichiers, par exemple si vous avez un imprévu match.
je le trouve très utile pour faire des modifications de source et renommer des symboles (variables, noms de fonction, etc.) sur l'ensemble du projet.
si vous ne savez pas déjà / utilisez le mode iedit c'est très pratique outil, je vous recommande fortement de donner un coup d'oeil.
L'utilisation de dired pour revenir en bas d'un arbre de répertoire profond va être un peu lent pour cette tâche. Vous pourriez envisager d'utiliser tags-query-remplacer . Cela signifie qu'il faut s'élancer pour créer une table tags, mais c'est souvent utile de toute façon, et c'est rapide.
Projectile est vraiment agréable: C-c P R exécute le projectile de commande-Remplacer
Source d'information: 1
pour les utilisateurs d'emacs pro:
- appel dirigé pour lister les fichiers dans dir, ou appel find-dired si vous avez besoin de tous les sous-répertoires.
- marquez les fichiers que vous voulez. Vous pouvez marquer par regex en tapant pax.
- Tapez Q pour appeler dired-do-query-replace-regexp.
- Tapez votre find regex et remplacez string. 〔☛ common elisp regex pattern"
- pour chaque événement, type y à remplacer, n À Sauter. Type de contrat Ctrl+G can avorter l'ensemble de l'opération. Type
- ! pour remplacer tous les événements dans le fichier courant sans demander, N de sauter tous les remplacements possibles pour le reste du fichier courant. (N est emacs 23 uniquement)
- pour effectuer le remplacement sur tous les fichiers sans autre demande, tapez Y. (Emacs 23 seulement)
- appeler ibuffer pour tout ouvrir fichier. Type 【* u】 pour marquer tous les fichiers non enregistrés, type S pour enregistrer tous les fichiers marqués, type de D pour les fermer toutes.
guide étape par étape pour les débutants Emacs
Sélectionner Les Fichiers Cibles
Démarrer emacs en tapant "emacs" dans l'interface de ligne de commande d'invite. (Ou, double-cliquez L'icône Emacs si vous êtes dans un environnement D'Interface utilisateur graphique)
sélectionner des fichiers dans un répertoire
vous devez d'abord sélectionner les fichiers que vous voulez remplacer. Utilisez le menu graphique po ur ouvrir le répertoire. Emacs vous demandera un chemin de répertoire. Tapez le chemin du répertoire, puis appuyez sur Entrée.
Maintenant, vous allez voir la liste des fichiers, et maintenant vous devez marquer les fichiers sur lesquels vous voulez que le regex find/replace fonctionne. Vous marquez un fichier en déplaçant le curseur sur le fichier que vous voulez, puis appuyez sur M. Détachez - le en appuyant sur U. (To list subdirectories, move votre curseur sur le répertoire et appuyez sur I. Le contenu du sous-répertoire sera listé en bas.) Pour marquer tous les fichiers par un regex, tapez "p", puis tapez votre motif regex. Par exemple, si vous voulez marquer tous les fichiers HTML, tapez alors "pip".HTML.$ (Vous pouvez trouver une liste des commandes mark dans le menu graphique "Mark" (Ce menu apparaît lorsque vous êtes en mode dirigé).)
sélection de fichiers dans un répertoire et tous ses sous-répertoires
si vous vous voulez faire trouver / remplacer sur des fichiers à l'intérieur d'un répertoire, y compris des centaines de sous-répertoires, voici une méthode pour sélectionner tous ces fichiers.
appelez find-dired. (vous appelez une commande en appuyant sur Option Alt+X Monet) alors, tapez un nom de répertoire, փ / Users / mary /myfiles
Note: Si vous utilisez emacs sur un terminal de texte non graphique unix, et si la Option Alt+X փ ne fonctionne pas, la touche clé équivalente est l'option ESC x փ.
Emacs vous demandera avec le prompt "Exécuter en trouver (avec des arguments): ". Si vous avez besoin de faire le remplacement sur tous les fichiers HTML, alors tapez-nom "*html". Si vous ne vous souciez pas de quel type de fichier mais simplement de tous les fichiers sous ce dir, alors donnez "-type f".
Maintenant, marquez les fichiers comme décrit ci-dessus.
"151900920 Interactif" Rechercher/Remplacermaintenant, vous êtes prêt à faire le remplacement de find interactif. Pour simplifier, disons que vous voulez juste de remplacer le mot "rapide" par "super". Maintenant, appelez - dired-do-query-replace-regexp. Il vous demandera la chaîne regex et la chaîne de remplacement. Tapez "rapide", Entrez, puis "super".
maintenant, emacs va utiliser votre motif et vérifier les fichiers, et s'arrêter et vous montrer chaque fois qu'une correspondance s'est produite. Lorsque cela se produit, emacs vous demande, et vous avez le choix de faire le changement ou d'ignorer le changement. Pour faire le changement, tapez Y. Pour sauter, tapez N. Si vous voulez simplement qu'emacs fasse toutes ces modifications dans le fichier courant, type de !.
si vous voulez annuler l'ensemble de l'opération sans enregistrer les changements que vous avez faits, tapez փ Ctrl+G փ փ փ, puis quittez emacs en utilisant le menu փ file փ փ փ Exit Emacs փ.
enregistrer les fichiers modifiés
maintenant, après que vous avez traversé l'épreuve ci-dessus, il y a une étape de plus que vous devez faire, et qui est de sauvegarder les fichiers modifiés.
si vous utilisez la version 22 ou une version ultérieure d'emacs, appelez ibuffer pour entrer dans un buffer liste mode, puis tapez 【* u】 pour marquer tous les fichiers non enregistrés, puis tapez S pour les sauver tous. (maj-s)
si vous utilisez une version 21 d'emacs, alors vous pouvez faire ceci: appeler des tampons de liste, puis déplacer le curseur vers le fichier que vous voulez enregistrer et taper. Il marquera le fichier pour enregistrer plus tard l'action. Tapez u à unmark. Une fois que vous avez terminé, tapez x pour exécuter la sauvegarde de tous les fichiers marqués pour la sauvegarde. (dans emacs, le fichier ouvert est appelé "buffer". Ignorer les autres choses.)
Alternative aux options ci-dessus, vous pouvez également appeler save-some-buffers փ Ctrl+x s փ. Ensuite, emacs affichera chaque fichier non sauvegardé et vous demandera si vous voulez qu'il soit sauvegardé.
Note: le regex d'emacs n'est pas le même que Perl ou Python, mais similaire. Pour un résumé et des modèles communs, voir: Emacs Regex.
M-X Dired
, et t pour sélectionner tous les fichiers, et Q
à une requête de remplacement de texte dans chacun d'eux.
Vous pouvez étendre un sous-répertoire en utilisant la commande i
avant la requête-replace.
Si vous donnez un préfixe (control-u) à la commande i,
il vous demandera pour arg, et-R argument sera d'étendre de façon récursive tous subdirs
dans le tampon dired
. Donc maintenant vous pouvez interroger-rechercher chaque dossier dans un répertoire entier.
pour les tampons ouverts, c'est ce que je fais:
(defun px-query-replace-in-open-buffers (arg1 arg2)
"query-replace in all open files"
(interactive "sRegexp:\nsReplace with:")
(mapcar
(lambda (x)
(find-file x)
(save-excursion
(goto-char (point-min))
(query-replace-regexp arg1 arg2)))
(delq
nil
(mapcar
(lambda (x)
(buffer-file-name x))
(buffer-list)))))
une autre option est d'utiliser Icicles search . Il s'agit d'un autre type de recherche incrémentale qui utilise l'achèvement de votre entrée minibuffer contre des résultats de recherche. Au fur et à mesure que vous modifiez vos entrées actuelles, l'ensemble des hits correspondants est mis à jour dans la mémoire tampon *Completions*
.
vous pouvez rechercher n'importe quel nombre de dossiers, tampons, ou emplacements de marque-page, que vous pouvez choisir en utilisant le motif de minibuffer (par exemple regexp) correspondant.
quand vous vous pouvez remplacer sur demande soit le hit entier ou juste la partie de celui-ci qui correspond à votre entrée minibuffer actuelle. Le remplacement à la demande signifie que vous n'êtes pas interrogé au sujet de chaque résultat de recherche à tour de rôle; vous accédez aux résultats que vous voulez directement, dans n'importe quel ordre. Cette approche peut être plus efficace que query-replace si vous avez un nombre limité de remplacements à faire: vous sautez l'interrogation exhaustive y/n
.
la recherche est terminée rechercher contextes que vous définissez -- vous n'êtes pas limité à rechercher tout le texte dans les fichiers cibles (par exemple, vous pouvez sauter des commentaires ou des types particuliers de sections de programme). Un exemple simple de contexte de recherche est une ligne, comme dans grep
, mais un contexte peut être n'importe quel bloc de texte que vous aimez. Typiquement, vous définissez les contextes de recherche en utilisant un regexp, mais vous pouvez à la place utiliser une fonction. En plus de définir votre propre, Il ya des Icicles prédéfinis commandes de recherche pour différents types de contextes: blocs de propriétés de texte ou propriétés de superposition, choses-à-point, etc.
vous pouvez aussi trier la recherche frappe dans divers ordres de tri pour faciliter l'accès/la navigation.
find-name-dired
est OK, mais:
- tous les fichiers que vous obtenez correspondent au même, un seul regexp.
-
find-dired
est plus souple à cet égard, mais il est également conçu pour utiliser des règles générales (même si elles peuvent être arbitrairement complexes). Et bien sûrfind
a son propre langage complexe. - si vous voulez alors agir sur seulement quelques-uns des fichiers dont les noms ont été recueillis dans le tampon
find(-name)-dired
, vous besoin de les marquer ou supprimer / omettre les lignes de ceux que vous ne voulez pas agir.
une alternative est d'utiliser Dired+ les commandes qui agissent sur (a) les fichiers marqués et (b) tous les fichiers marqués (ou tous les fichiers, si aucun n'est marqué) dans les sous-répertoires marqués ... trouvé récursivement . Cela vous donne à la fois généralité et facile contrôle sur le choix du fichier. Ces commandes " here-and-below "sont toutes sur la touche de préfixe M-+
en mode dirigé.
par exemple, M-+ Q
est le même que Q
- - - query-replace, mais les fichiers cibles sont tous ceux marqués dans le dir actuel et dans tous les sous-dirs marqués, vers le bas, vers le bas...
Oui, une alternative à l'utilisation de tel ici et ci-dessous commandes insérer tous les sous-répertoires et leurs sous-répertoires, de façon récursive, puis utilisez une commande de haut niveau comme Q
. Mais il peut souvent être pratique de ne pas s'embêter avec des sous-répertoires insérés.
et pour ce faire, vous avez de toute façon besoin d'un moyen rapide à insérer tous ces sous-répertoires récursivement . Ici aussi, Dired+ peut aider. M-+ M-i
insère tous les sous-répertoires marqués et leurs propres sous-répertoires Marqués, de façon récursive. Que is, il est comme M-i
(qui insère les sousdirs marqués dans Dired+ ), mais il agit récursivement sur les sousdirs.
(toutes les commandes" ici-et-dessous " dirigées+ sont sur le menu Multiple > marquées ici et en dessous .)
vous pouvez également effectuer des opérations dirigées sur un Emacs fileset , qui est un ensemble enregistré de noms de fichiers situé n'importe où. Et si vous utilisez Glaçons , alors vous pouvez ouvrir un Dired tampon pour seulement les fichiers dans un fileset ou d'autres types de fichier enregistré listes.
vous pouvez aussi bookmark n'importe quel tampon, y compris celui que vous créez en utilisant find(-name)-dired
. Cela vous donne un moyen rapide de revenir à un tel ensemble (par exemple un ensemble de projet) plus tard. Et si vous utilisez marque-page+ puis le bookmarking d'un tampon dirigé enregistre (a) ses commutateurs ls
, (b) quels fichiers sont marqués, (c) quels sous-répertoires sont insérés, et (d)quels (sous) répertoires sont cachés. Tout cela est restauré lorsque vous "sauter" vers le signet. marque-page+ vous permet également de marquer un arbre entier de tampons dirigés - - saut à la marque - page rétablit tous les tampons dans l'arbre.
je voudrais suggérer un autre grand outil qui n'a pas encore été mentionné, à savoir Helm .
c'est un excellent remplacement pour de nombreuses opérations standard D'Emacs impliquant l'achèvement, la recherche, etc. En particulier, helm-find-files
permet d'effectuer le remplacement de requête (y compris regexp) dans plusieurs fichiers sélectionnés.
Just open helm-find-files
, marquer les fichiers pertinents avec M-SPC
puis utilisez F6
ou F7
pour lancer la requête remplacer ou la requête remplacer regexp dans les fichiers sélectionnés.
ce n'est pas Emacs, mais xxdiff est livré avec un outil appelé xx-rename qui le fera pour plusieurs chaînes à la fois (par exemple de à de à de à), avec des invites interactives, sauvegarde des sauvegardes de tous les fichiers modifiés, et produit un petit journal des modifications faites avec le contexte. C'est ce que j'ai tendance à utiliser quand je fais de grands/global renamings.