Rechercher et remplacer des chaînes dans vim sur plusieurs lignes

354

Je peux faire :%s/<search_string>/<replace_string>/gpour remplacer une chaîne dans un fichier, ou :s/<search_string>/<replace_string>/pour remplacer dans la ligne actuelle.

Comment puis-je sélectionner et remplacer des mots à partir de lignes sélectives dans vim?

Exemple: remplacez le texte des lignes 6-10, 14-18mais pas de 11-13.

mu 無
la source

Réponses:

255

La :&&commande répète la dernière substitution avec les mêmes drapeaux. Vous pouvez lui fournir la ou les plages supplémentaires (et en concaténer autant que vous le souhaitez):

:6,10s/<search_string>/<replace_string>/g | 14,18&&

Si vous avez de nombreuses plages , je préfère utiliser une boucle:

:for range in split('6,10 14,18')| exe range 's/<search_string>/<replace_string>/g' | endfor
Ingo Karkat
la source
5
Merci. Remarque pour les futurs utilisateurs - :6,10s/<search_string>/<replace_string>/g | :14,18&& | :20,23&& | :28,31&&fonctionnera également, la forboucle facilite la mémorisation et l'exécution.
mu 無
5
Content que tu aimes ça! Le :sur les commandes suivantes est facultatif, btw, afin que vous puissiez enregistrer quelques frappes supplémentaires.
Ingo Karkat du
2
:&&me fera économiser des centaines de frappes par semaine. Merci!
pdoherty926
Cela fonctionne sans le «g» à la fin dans mon vim. Alors peut-être que lorsque vous spécifiez la plage de lignes, il n'a pas besoin d'un indicateur global
Tayyar R
3
@TayyarR La plage couvre les lignes (verticalement, pour ainsi dire), tandis que le drapeau «g» détermine si une ou toutes les correspondances de la ligne (donc horizontalement) sont remplacées.
Ingo Karkat
387

Remplace tout:

:%s/foo/bar/g

Trouvez chaque occurrence de 'foo' (sur toutes les lignes) et remplacez-la par 'bar'.

Pour des lignes spécifiques:

:6,10s/foo/bar/g

Remplacez chaque "foo" par "bar" pour toutes les lignes de la ligne 6 à la ligne 10 inclus.

Jayanth Ramachandran
la source
4
quel est le but de / g ici? Désolé, je suis nouveau sur Linux
Raja Anbazhagan
4
@RajaAnbazhagan La dernière partie de cette expression, après la dernière /, est l'endroit où vous indiquez des indicateurs pour l'opération. Cette commande remplacera normalement la première correspondance sur une ligne; Avec le gdrapeau, il remplacera toutes les occurrences.
Litty
17
Vous devriez vraiment référencer vos sources (par exemple, vim.wikia.com/wiki/Search_and_replace), si vous allez copier et coller le travail d'une autre personne.
Andrew S
2
La %chose fait le travail! Sinon, ce n'est que la première occurrence.
Santosh Kumar
8
%=> exécutez cette commande sur toutes les lignes. g=> correspondre à plusieurs occurrences sur la même ligne.
shaahiin
55

En remarque, au lieu d'avoir à taper les numéros de ligne, mettez simplement en surbrillance les lignes où vous souhaitez trouver / remplacer dans l'un des modes visuels:

  • VISUALmode ( V)
  • VISUAL BLOCKmode ( Ctrl+ V)
  • VISUAL LINEmode ( Shift+ V, fonctionne mieux dans votre cas)

Une fois que vous avez sélectionné les lignes à remplacer, tapez votre commande:

:s/<search_string>/<replace_string>/g

Vous remarquerez que la plage '<,'>sera insérée automatiquement pour vous:

:'<,'>s/<search_string>/<replace_string>/g

Ici '<signifie simplement la première ligne en surbrillance et '>signifie la dernière ligne en surbrillance .

Notez que le comportement peut être inattendu en NORMALmode: '<et '>pointez sur le début et la fin de la dernière surbrillance effectuée dans l'un des VISUALmodes. Au lieu de cela, en NORMALmode, le numéro de ligne spécial .peut être utilisé, ce qui signifie simplement la ligne actuelle . Par conséquent, vous ne pouvez trouver / remplacer que sur la ligne actuelle comme ceci:

:.s/<search_string>/<replace_string>/g

Une autre chose à noter est que l'insertion d'une seconde :entre la plage et la commande find / replace ne fait aucun mal, en d'autres termes, ces commandes fonctionneront toujours:

:'<,'>:s/<search_string>/<replace_string>/g
:.:s/<search_string>/<replace_string>/g
Attila O.
la source
1
> Exemple: remplacez le texte des lignes 6-10, 14-18 mais pas de 11-13. - votre réponse ne répond-elle pas à cette question, n'est-ce pas?
poige
27

Vous pouvez le faire avec deux séquences de recherche / remplacement

  :6,10s/<search_string>/<replace_string>/g
  :14,18s/<search_string>/<replace_string>/g

La deuxième fois, tout ce dont vous avez besoin pour régler est la plage, donc au lieu de tout taper, je rappellerais la dernière commande et éditerais juste la plage

Lieven Keersmaekers
la source
21

Dans vim si vous ne savez pas quelles lignes seront affectées, utilisez ci-dessous

 :%s/foo/bar/gc  

Changez chaque «foo» en «bar», mais demandez d'abord une confirmation. Appuyez sur 'y' pour oui et sur 'n' pour non. N'oubliez pas de sauvegarder après cela

:wq
SMJ
la source
2
Vous pouvez réellement utiliser l' cindicateur en plus de spécifier la plage, donc ça :6,10s/<search_string>/<replace_string>/cmarche. creprésente confirm. J'utilise le cdrapeau assez souvent pour éviter de remplacer accidentellement des mots où je ne pensais pas qu'ils existaient également.
Wolfson
16

Exemples de commandes de recherche et de remplacement de VI

Disons que vous souhaitez trouver un mot appelé "foo" et le remplacer par "bar".

Première touche [Esc]enfoncée

Tapez: (deux-points) suivi de %s/foo/bar/et appuyez sur la touche [Entrée]

:%s/foo/bar/

Arnav
la source
11
Votre :%s/<search_string>/<replace_string>/gcommande remplacera toutes les occurrences du fichier entier. Pas exactement la réponse à la question, mais néanmoins utile :)
tanius
@tanius En fait, c'était la réponse la plus simple à mon problème. Vous pouvez envisager de modifier la question en "Rechercher et remplacer les chaînes dans vim sur les lignes" sélectionnées ""
Omid N
9

Nous n'avons pas besoin de prendre la peine de saisir le numéro de ligne actuel.

Si vous souhaitez modifier chaque fooà la barligne actuelle ( .) et les deux lignes suivantes ( +2), il suffit de faire:

:.,+2s/foo/bar/g

Si vous souhaitez confirmer avant d'apporter des modifications, remplacez gpar gc:

:.,+2s/foo/bar/gc
lingjiankong
la source
Une autre bonne chose que j'utilise souvent est :.,$s/foo/bar/gcde rechercher et de remplacer à partir de la ligne actuelle jusqu'à la fin du fichier.
Wolfson
3

Rechercher et remplacer

:%s/search\|search2\|search3/replace/gci

g => recherche globale

c => Demandez d'abord la confirmation

i => insensible à la casse

Si vous souhaitez un remplacement direct sans confirmation, utilisez la commande ci-dessous

:%s/search/replace/g

Si vous souhaitez une confirmation pour chaque remplacement, exécutez la commande ci-dessous

:%s/search/replace/gc

Demandez d'abord une confirmation, ici la recherche ne respectera pas la casse.

:%s/search/replace/gci
Rahul Ravi
la source
1

La spécification de la plage par sélection visuelle est correcte, mais lorsqu'il y a des opérations très simples sur seulement quelques lignes qui peuvent être sélectionnées par un opérateur, le mieux serait d'appliquer ces commandes en tant qu'opérateurs.

Cela ne peut malheureusement pas être fait via les commandes standard de vim. Vous pouvez faire une sorte de solution de contournement en utilisant le! (filtre) et tout objet texte. Par exemple, pour appliquer l'opération à un paragraphe, vous pouvez faire:

!ip

Cela doit être lu comme "Appliquer l'opérateur! À l'intérieur d'un paragraphe". L'opérateur de filtre démarre le mode de commande et insère automatiquement la plage de lignes suivie d'un littéral "!" que vous pouvez supprimer juste après. Si vous appliquez ceci, au paragraphe suivant:

1
2  Repellendus qui velit vel ullam!
3  ipsam sint modi! velit ipsam sint
4  modi! Debitis dolorum distinctio
5  mollitia vel ullam! Repellendus qui
6  Debitis dolorum distinctio mollitia
7  vel ullam! ipsam
8
9  More text around here

Le résultat après avoir appuyé sur "! Ap" serait comme:

:.,.+5

Comme le '.' (point) signifie que la ligne actuelle, la plage entre la ligne actuelle et les 5 lignes suivantes seront utilisées pour l'opération. Vous pouvez maintenant ajouter la commande de substitution de la même manière que précédemment.

La mauvaise partie est que ce n'est pas plus facile que de sélectionner le texte pour ce dernier en appliquant l'opérateur. La bonne partie est que cela peut répéter l'insertion de la plage pour d'autres plages de texte similaires (dans ce cas, les paragraphes) avec une taille visiblement différente. C'est-à-dire, si vous souhaitez par la suite sélectionner le plus grand paragraphe de la plage, le '.' le fera bien.

De plus, si vous aimez l'idée d'utiliser des objets texte sémantiques pour sélectionner la plage d'opération, vous pouvez vérifier mon plugin EXtend.vim qui peut faire de même mais de manière plus simple.

Saul Axel Martinez Ortiz
la source
0

Pour répondre à cette question:

:40,50s/foo/bar/g

remplacez foo par bar dans ces lignes entre la 40e ligne et la 50e ligne (inclus), lorsque vous exécutez cette commande, vous pouvez actuellement sur n'importe quelle ligne.

:50,40s/foo/bar/g

fonctionne également, vim vous demandera de confirmer, puis effectuera le remplacement pour vous comme si vous aviez entré la première commande.

:,50s/foo/bar/g

remplacez foo par bar dans ces lignes entre la ligne dans laquelle vous vous trouvez actuellement et la 50e ligne (incluse). (si vous êtes dans une ligne APRÈS la 50e ligne, vim vous demandera de confirmer à nouveau)

Pour clarifier la différence entre vim et le plugin vrapper d'Eclipse:

Notez que dans varpper

:,50s/foo/bar/g la commande ne fonctionnera PAS.

:50,40s/foo/bar/g fonctionnera sans demander de confirmation.

(Pour Vrapper version 0.74.0 ou antérieure).

ZhaoGang
la source
-5
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal

Supposons que vous souhaitiez remplacer ce qui précède par d'autres informations.

COMMAND(:%s/\/sys\/sim\/source\/gm\/kg\/jl\/ls\/owow\/lsal/sys.pkg.mpu.umc.kdk./g)

En cela, ce qui précède sera remplacé par ( sys.pkg.mpu.umc.kdk.).

Sai Ganesh
la source
Je ne suis pas sûr que cela réponde réellement à la question. D'après la question, il apparaît que la personne interrogée sait déjà comment utiliser %spour modifier l'entrée mais veut savoir comment le faire "semi-globalement" (c'est-à-dire que sa spécification est les lignes 6-10 et 14-18 mais pas les lignes 11- 13).
Brandon Buck
1
Qu'est-ce que "COMMAND"? Et vous souffrez du syndrome du cure-dent penché .
Martin Tournoij
Pour guérir que le syndrome, vous pouvez utiliser un autre caractère comme séparateur au lieu de la valeur par défaut /, par exemple !, @, _::%s_/sys/sim/source/gm/kg/jl/ls/owow/lsal_sys.pkg.mpu.umc.kdk_g
MortezaE