Vim: insérez les mêmes caractères sur plusieurs lignes

306

Parfois, je veux modifier un certain bloc visuel de texte sur plusieurs lignes.

Par exemple, je prendrais un texte qui ressemble à ceci:

name
comment
phone
email

Et fais comme ça

vendor_name
vendor_comment
vendor_phone
vendor_email

Actuellement, la façon dont je le ferais maintenant est ...

  1. Sélectionnez les 4 lignes d'un bloc en appuyant sur Vpuis sur jquatre fois.
  2. Retrait avec >.
  3. Remontez une lettre avec h.
  4. Passez en mode visuel bloqué avec Ctrlv.
  5. Sélectionnez quatre lignes vers le bas en appuyant jquatre fois. À ce stade, vous avez sélectionné un bloc visuel 4x1 d'espaces blancs (quatre lignes et une colonne).
  6. Appuyez sur C. Remarquez ceci à peu près en retrait à gauche d'une colonne.
  7. Tapez un " vendor_"sans le devis. Remarquez l'espace supplémentaire que nous avons dû remettre.
  8. Appuyez sur Esc. C'est l'une des rares fois que j'utilise Escpour sortir du mode d'insertion. Ctrlcne modifierait que la première ligne.
  9. Répétez l'étape 1.
  10. Retrait dans l'autre sens avec <.

Je n'ai pas besoin de mettre en retrait s'il y a au moins une colonne d'espace avant les mots. Je n'aurais pas besoin de l'espace blanc si je n'avais pas à effacer le bloc visuel avec c.

Mais si je dois effacer, existe-t-il un moyen de faire ce que j'ai effectué ci-dessus sans créer les espaces nécessaires avec indentation?

Aussi pourquoi l'édition de plusieurs lignes à la fois ne fonctionne-t-elle qu'en quittant le mode d'insertion avec Escover Ctrlc?


Voici un exemple plus compliqué:

name    = models.CharField( max_length = 135 )
comment = models.TextField( blank = True )
phone   = models.CharField( max_length = 135, blank = True )
email   = models.EmailField( blank = True )

à

name    = models.whatever.CharField( max_length = 135 )
comment = models.whatever.TextField( blank = True )
phone   = models.whatever.CharField( max_length = 135, blank = True )
email   = models.whatever.EmailField( blank = True )

Dans cet exemple, je voudrais effectuer le bloc visuel vertical sur le ., puis le réinsérer en mode insertion, c'est-à-dire taper .whatever.. J'espère que vous pouvez maintenant voir l'inconvénient de cette méthode. Je me limite à sélectionner uniquement une colonne de texte qui sont toutes identiques en position verticale .

hobbes3
la source
9
Meilleure façon: ":% s / ^ / vendor_ /"
Paul Tomblin
1
Merci pour la réponse. Cela fonctionne si je veux seulement ajouter un mot à chaque ligne. Mais la méthode que j'utilise peut se faire à n'importe quelle position. Permettez-moi d'ajouter un autre mon exemple avec un exemple plus compliqué.
hobbes3
3
Mettez ensuite en surbrillance les lignes que vous souhaitez modifier avec shift-V, et tapez une commande de recherche et de remplacement appropriée - dans le deuxième exemple,:s/models\./\0whatever./
Paul Tomblin
De nombreuses façons d'atteindre ce qui précède. Pour répondre pleinement à toutes les parties de la question, puis la partie 1) soit en mode regex ou en mode visuel, je modifie esc fonctionne bien comme proposé dans les réponses (je préfère la sélection visuelle dans GVIM). Pour la partie 2), la macro est peut-être la plus simple comme proposé par Brian Neal. La meilleure ressource que je connaisse pour tous ces types de "comment faire" est Practical Vim de Drew Neil. Excellente lecture rapide et référence légère lorsque vous oubliez une formule. J'espère que cette recommandation aidera quelqu'un, cela en vaudra la peine pour de nombreux utilisateurs de vim.
arcseldon
@Paul: Et si vous comptez les frappes , vous pouvez remplacer \0par &.
icktoofay

Réponses:

912
  1. Déplacez le curseur sur l' nen name.
  2. Passez en mode de blocage visuel ( Ctrlv).
  3. Appuyez jtrois fois (ou 3j).
  4. Appuyez sur I(majuscule i).
  5. Tapez vendor_. Remarque: Il ne mettra à jour l'écran que dans la première ligne - jusqu'à ce que vous Escappuyiez sur (6.), auquel point toutes les lignes seront mises à jour.
  6. Appuyez sur Esc.

mini-screencast démontrant la méthode

Une majuscule Idoit être utilisée plutôt qu'une minuscule i, car la minuscule iest interprétée comme le début d'un objet texte , ce qui est plutôt utile en soi, par exemple pour sélectionner à l'intérieur d'un bloc de balises ( it):

mini-screencast montrant l'utilité de l'objet texte 'it'

icktoofay
la source
12
Je n'ai pas pu faire fonctionner cela dans Windows (puisque CTRL + V est mappé pour la pâte du presse-papiers). Mais Vim a également mappé cela à Ctrl + Q pour la version Windows.
Arnestig
2
@Ven: Vim n'est pas vraiment occupé pendant cette période - il n'attend que vous pour appuyer sur une autre touche, et finalement expire. Deux expériences pour vous: d'abord, essayez d'appuyer sur Échap, puis appuyez immédiatement sur une autre touche, comme jou ^L. Vous devriez voir que Vim n'était pas occupé après tout; c'était juste en attente. Deuxièmement, essayez de passer 'timeout'à une valeur inférieure, comme 80(plutôt que par défaut 1000) et observez qu'elle expire plus rapidement.
icktoofay
1
@icktoofay Il semble que la variable que vous souhaitez définir timeoutlenne le soit pas timeout.
2014
4
@ANjaNA: Si l'endroit où vous voulez insérer est tout dans la même colonne (par exemple si les nombres sont tous de la même longueur), vous pouvez utiliser la même technique sauf en appuyant sur Aplutôt que I, qui s'insérera après le bloc sélectionné plutôt qu'avant. Si vos lignes sont de longueurs différentes, cela ne fonctionnera pas; J'aime utiliser une substitution correspondant à la fin de chaque ligne pour cela, par exemple en sélectionnant certaines lignes et en utilisant :s/$/inserted/.
icktoofay
3
J'ai dû appuyer sur la flèche vers le bas après avoir appuyé sur esc pour que cela fonctionne
GeoSword
69

Une autre approche consiste à utiliser la commande .( dot) en combinaison avec I.

  1. Déplacez le curseur où vous voulez commencer
  2. presse I
  3. Tapez le préfixe que vous souhaitez (par exemple vendor_)
  4. Appuyez sur esc.
  5. Appuyez jpour descendre une ligne
  6. Tapez .pour répéter la dernière modification, en insérant automatiquement à nouveau le préfixe
  7. Alterner rapidement entre jet.

Je trouve que cette technique est souvent plus rapide que le mode de blocage visuel pour un petit nombre d'ajouts et présente l'avantage supplémentaire que si vous n'avez pas besoin d'insérer le texte sur chaque ligne d'une plage, vous pouvez facilement les ignorer en appuyant sur les touches supplémentaires j. .

Notez que pour un grand nombre d'ajouts contigus, l'approche par bloc ou la macro sera probablement supérieure.

danprice
la source
Ravi de voir une autre approche.
Ibn Saeed
Je préfère cela pour seulement quelques lignes. Beaucoup plus facile à exécuter IMO.
Dan Bechard
Après avoir tapé le préfixe que vous voulez, n'avez-vous pas besoin d'appuyer sur la touche d'échappement?
iamnotsam
41
  1. Sélectionnez les lignes que vous souhaitez modifier à l'aide de CtrlV.
  2. Presse:

    • I: Insérer avant ce qui est sélectionné.
    • A: Ajouter après ce qui est sélectionné.
    • c: Remplacer ce qui est sélectionné.
  3. Tapez le nouveau texte.

  4. Appuyez sur Escpour appliquer les modifications à toutes les lignes sélectionnées.
Loukan ElKadi
la source
4
Excellent! Je voudrais juste souligner l'étape finale Escpour les noobs VIM comme moi - il m'a fallu un certain temps pour comprendre que les changements se propagent "plus tard"!
Bugs Bunny
1
Bien, je ne connaissais pas non plus les options "A" et "C".
hobbes3
Pourquoi ça ne marche pas v? Je peux le faire avec Ctrl+V --> A, mais faire vpour sélectionner le texte ne fonctionne pas - Ane s'ajoute qu'à cette ligne. N'est-ce pas tous les deux une sélection? Aussi, très étrange - Ane s'ajoute qu'à la fin de la ligne SI j'étends le bloc visuel jusqu'à la fin de la ligne; sinon, il s'ajoute à la fin du bloc visuel pour chaque ligne. C'est comme s'il ne reconnaissait pas la différence entre aet A.
Alex G
1
J'avais besoin d'utiliser à la cplace de C, mais cela fonctionnait parfaitement bien. Merci
Tarol
29

J'utiliserais une macro pour enregistrer mes actions, puis je la répéterais.

  1. Placez votre curseur sur la première lettre du nom .
  2. Frappé qq pour démarrer l'enregistrement dans le tampon q.
  3. Appuyez sur ipour passer en mode d'insertion, tapez vector_ , puis appuyez surEsc pour quitter le mode d'insertion.
  4. Maintenant frappé 0 pour revenir au début de la ligne.
  5. Maintenant frappé j pour descendre.
  6. Appuyez à qnouveau pour arrêter l'enregistrement.

Vous avez maintenant une belle macro.

Tapez 3@qpour exécuter votre macro trois fois pour effectuer le reste des lignes.

Brian Neal
la source
"Q" est-il spécial (pour "macro rapide"?)?
Peter Mortensen
Comment rendre la macro persistante (en travaillant sur plusieurs sessions)?
Peter Mortensen
@PeterMortensen Vim a une fonctionnalité appelée sessions qui persistera les tampons (et beaucoup d'autres choses) que vous pouvez examiner.
Brian Neal
27
:%s/^/vendor_/

ou est-ce que je manque quelque chose?

srini.venigalla
la source
Vous manquez le fait qu'il s'agit probablement d'un sous-texte dans un fichier avec de nombreuses autres lignes sur lesquelles le vender_préfixe n'est pas souhaité.
Dan Bechard
9
@dan Si seul un sous-texte est nécessaire, vous pouvez limiter la recherche à un ensemble de numéros de ligne, par exemple1,4s/^/vendor_/
Brad Koch
1
@BradKoch Intéressant. Je n'étais pas au courant des contraintes de numéro de ligne, merci pour cela.
Dan Bechard
8
c'est intéressant, mais ce qui est plus pratique, c'est de bloquer visuellement la sélection avec Vet le type :. Il préfixera l'expression ed avec :'<,'>laquelle faire ed ne s'applique qu'à la sélection avec:'<,'>s/^/vendor_/
Dolanor
12

Mise à jour janvier 2016

Bien que la réponse acceptée soit une excellente solution, il s'agit en fait d'un nombre légèrement moins élevé de touches et d'une meilleure échelle - en principe en fonction de la réponse acceptée.

  1. Déplacez le curseur sur l' nen name.
  2. Passez en mode de blocage visuel ( ctrlv).
  3. presse 3j
  4. Appuyez sur I.
  5. Tapez vendor_.
  6. Appuyez sur esc.

illustration visuelle

Notez que cela a moins de touches que la réponse acceptée fournie (comparez l'étape 3). Nous comptons simplement le nombre d'actions j à effectuer.

Si vous avez activé les numéros de ligne (comme illustré ci-dessus) et connaissez le numéro de ligne vers lequel vous souhaitez vous déplacer, l'étape 3 peut être remplacée par #G lequel où # est le numéro de ligne souhaité.

Dans notre exemple ci-dessus, ce serait 4G. Cependant, lorsqu'il s'agit de quelques numéros de ligne, un décompte explicite fonctionne bien.

arcseldon
la source
7

Je voulais commenter beaucoup de lignes dans un fichier de configuration sur un serveur qui n'avait que vi (pas de nano), donc la méthode visuelle était également lourde. Voici comment j'ai fait cela.

  1. Fichier ouvert vi file
  2. Afficher les numéros de ligne :set number!ou:set number
  3. Utilisez ensuite les numéros de ligne pour remplacer le début de ligne par "#", comment?

:35,77s/^/#/

Remarque: les numéros sont inclus, les lignes de 35 à 77, les deux incluses seront modifiées.

Pour décommenter / annuler cela, utilisez simplement :35,77s/^#//

Si vous souhaitez ajouter un mot de texte comme commentaire après chaque ligne de code, vous pouvez également utiliser:

:35,77s/$/#test/ (pour les langages comme Python)

:35,77s/;$/;\/\/test/ (pour les langages comme Java)

crédits / références:

  1. /unix/84929/uncommenting-multiple-lines-of-code-specified-by-line-numbers-using-vi-or-vim

  2. /unix/120615/how-to-comment-multiple-lines-at-once

computingfreak
la source
C'était la solution parfaite pour moi car j'utilise souvent uniquement vim-tiny.
JSON C11
7

Vous pouvez également avoir un cas d'utilisation dans lequel vous souhaitez supprimer un bloc de texte et le remplacer.

Comme ça

Hello World

Hello World

À

Hello Cool

Hello Cool

Vous pouvez simplement bloquer visuellement sélectionner "Monde" dans les deux lignes.

Tapez cpour le changement - maintenant vous serez en mode insertion.

Insérez ce que vous voulez et appuyez sur Échap.

Les deux se reflètent verticalement. Il fonctionne exactement comme «I», sauf qu'il remplace le bloc par le nouveau texte au lieu de l'insérer.

Nishant
la source
6

Supposons que vous ayez ce fichier:

something

name
comment
phone
email

something else
and more ...

Vous souhaitez ajouter "fournisseur_" devant "nom", "commentaire", "téléphone" et "e-mail", quel que soit leur emplacement dans le fichier .

:%s/\<\(name\|comment\|phone\|email\)\>/vendor_\1/gc

Le cdrapeau vous demandera confirmation. Vous pouvez supprimer cela si vous ne voulez pas l'invite.

Manish
la source
5

Une alternative plus flexible:

Exemple: pour saisir le texte XYZ au début de la ligne

:%norm IXYZ

Qu'est-ce qu'il se passe ici?

  • % == Exécuter sur chaque ligne
  • norm == Exécute les touches suivantes en mode normal
  • I == Insérer au début de la ligne
  • XYZ == Le texte que vous souhaitez saisir

Ensuite, vous frappez Enter, et il s'exécute.

Spécifique à votre demande:

:%norm Ivendor_

Vous pouvez également choisir une gamme particulière:

:2,4norm Ivendor_

Ou exécutez sur une plage visuelle sélectionnée:

:'<,'>norm Ivendor_
Aubrey Lavigne
la source
1
est-il possible d'envoyer des séquences de touches comme <Esc> en mode insertion (norme Iabc <ESC>) afin de faire des choses plus intéressantes?
batbrat
1
@batbrat Je viens de comprendre cela! Vous pouvez appuyer sur ctrl-v ctrl-[pour insérer un "Esc échappé", ce qui vous ramène au "mode normal" aux fins de votre commande normale. Je viens de tester cela avec '<,'>norm Iaa^[ysiw", où ^[est le Esc échappé.
Aubrey Lavigne
4
Use Ctrl+V to enter visual block mode
Move Up/Down to select the columns of text in the lines you want to comment.
Then hit Shift+i and type the text you want to insert.
Then hit Esc, wait 1 second and the inserted text will appear on every line
Arpan Saini
la source
cette méthode fonctionne-t-elle pour toutes les versions de vim ou nécessite-t-elle des plugins vim? la raison pour laquelle je demande est b / c cela fonctionne parfois sur certaines machines, mais parfois non. je ne peux pas comprendre la différence. vim qui vient avec git sur windows - je ne peux pas le faire fonctionner. sur certaines machines Linux Ubuntu et Centos, je ne peux pas le faire fonctionner. j'ai eu du succès dans quelques rares cas, mais je n'ai pas pu reproduire le succès. c'est un mystère. rien ne semble se produire après avoir touché ESC.
davidj411
bizarrement, cela fonctionne pour moi maintenant. rien n'a changé, sauf peut-être les étoiles :) en cherchant une solution à mon problème, j'ai trouvé quelque chose sur cette page bien que cela mentionne quelque chose à rechercher dans vim vim.wikia.com/wiki/Inserting_text_in_multiple_lines Dans Vim, vérifiez que vous avez la fonction blockwise-operators (I, A et plus) en entrant la commande: version. La sortie doit inclure + visualextra.
davidj411
Je voulais ajouter un commentaire en général, pas à votre réponse. La plupart de ces réponses disent la même chose mais en utilisant des mots différents. Le mien avait quelque chose de différent à offrir et comprenait un lien.
davidj411
2
  1. Ctrl + v pour passer en mode bloc visuel
  2. Sélectionnez les lignes à l'aide des flèches haut et bas
  3. Entrez en minuscules 3i(appuyez sur minuscules I trois fois )
  4. I (capital presse I . Cela vous amènera en mode insertion.)
  5. Écrivez le texte que vous souhaitez ajouter
  6. Esc
  7. Appuyez sur la flèche vers le bas
Arpan Saini
la source