Comment répéter une modification sur plusieurs lignes dans Vim?

122

Je suis conscient que dans Vim, je peux souvent répéter une commande en ajoutant simplement un numéro devant elle. Par exemple, on peut supprimer 5 lignes par:

5dd

Il est également souvent possible de spécifier une plage de lignes à laquelle appliquer une commande, par exemple

:10,20s:hello:goodbye:gc

Comment puis-je effectuer une «modification verticale»? Je voudrais, par exemple, insérer un symbole particulier, disons une virgule, au début (sauter les espaces, c'est-à-dire ce que vous obtiendriez si vous tapez une virgule après Shift-I en mode commande) de chaque ligne dans un gamme. Comment cela peut-il être réalisé (sans recourir à la période de baisse-période-baisse-période-baisse)?

saffsd
la source

Réponses:

107

:10,20s/^/,/

Ou utilisez une macro, enregistrez avec:

q a i , ESC j h q

utiliser avec:

@ a

Explication: q acommence l'enregistrement d'une macro à enregistrer a, qtermine l'enregistrement. Il y a des registres aà zdisposition pour cela.

Svante
la source
Merci. Et si je voulais l'équivalent d'un shift-i? Autrement dit, sauter l'espace blanc initial?
saffsd
2
Explication: ^\(\s*\)capture l'espace blanc initial et l'enregistre dans un registre que vous pouvez ensuite lire \1.
Svante
136

Ctrl- vpasse en mode visuel par blocs. Vous pouvez ensuite vous déplacer (dans le hjklsens-sens, comme d'habitude), et si vous voulez insérer quelque chose sur plusieurs lignes, utilisez Shift- i.

Donc pour le texte:

abc123abc
def456def
ghi789ghi

si vous appuyez sur Ctrl- vavec votre curseur sur le 1, appuyez jdeux fois pour descendre de deux colonnes, puis Shift- i,ESC, votre texte ressemblerait à ceci:

abc,123abc
def,456def
ghi,789ghi

(l'insert multiligne a un petit décalage et ne sera rendu qu'après avoir frappé ESC).

rampion
la source
3
Agréable. Ctrl-V signifie majuscule, au fait, vous pourriez dire Ctrl-Shift-v
Svante
8
en fait, c'est CTRL-v ou CTRL-V. Vim est insensible à la casse pour les codes CTRL (voir: help CTRL- {char}).
rampion
2
après avoir cherché un peu pourquoi cette méthode ne fonctionnait pas, c'est parce qu'elle utilise un I majuscule (shift-i) au lieu de i (aussi, ce n'était que ctrl-v, car ctrl-shift-v m'a amené à la fin)
Willyfrog
4
Je suis curieux. Pourquoi n'utilisent-ils pas simplement isans la touche Majuscule?
off99555
1
i sans décalage est inséré à la position actuelle. shift + i est inséré au début de la ligne
Kevin P
59

C'est à cela que sert la commande: norm (al):

: 10,20 I normal,
Cyber ​​Oliveira
la source
44

Si vous utilisez déjà le '.' pour répéter beaucoup votre dernière commande, j'ai trouvé que c'était la solution la plus pratique à ce jour. Il vous permet de répéter votre dernière commande sur chaque ligne d'un bloc visuel en utilisant

" allow the . to execute once for each line of a visual selection
vnoremap . :normal .<CR>
gaufrer
la source
1
Ceci est utile mais également limité car il .fonctionne par ligne en mode visuel. Je pense que le mode visuel dans ce cas peut parfois être pratique pour sélectionner une plage de lignes. Mais les commandes et les macros sont plus flexibles et puissantes dans ce cas.
Bohr
23

Je pense que le moyen le plus simple de le faire est

1) enregistrez une macro pour une ligne, appelez-la «a»; dans ce cas on types

qa I, ESC jq

2) sélectionnez le bloc de lignes auquel vous souhaitez appliquer la macro

3) utiliser la fonction 'norm' pour exécuter la macro 'a' sur ce bloc de lignes, c'est-à-dire,

:'<,'>norm@a
Albert
la source
17

Je pense que le plus simple est d'enregistrer une macro, puis de répéter la macro autant de fois que vous le souhaitez. Par exemple, pour ajouter une virgule au début de chaque ligne, vous tapez:

q a I , ESC j q

pour répéter cela 5 fois, vous entrez

5 @ a
wimh
la source
2

J'utilise le mode visuel de bloc . Cela vous permet d'effectuer des insertions / modifications sur plusieurs lignes (également appelées «modifications verticales»).

ONODEVO
la source
1
votre lien est rompu
Christopher Hunter
2

Avec votre modification déjà enregistrée dans l' .opérateur, procédez comme suit:

  1. Sélectionnez le texte auquel vous souhaitez appliquer l'opérateur à l'aide du mode visuel
  2. Puis exécutez la commande :norm .
Noé
la source
1

En dehors des macros, comme déjà répondu, pour le cas spécifique de l'insertion d'une virgule dans une plage de lignes (par exemple de la ligne 10 à 20), vous pouvez faire quelque chose comme:

:10,20s/\(.*\)/,\1

Autrement dit, vous pouvez créer une correspondance de groupe numérotée avec \ (et \), et utiliser \ 1 dans la chaîne de remplacement pour dire "remplacer par le contenu de la correspondance".

Paolo Tedesco
la source