327 votes

Fusionner plusieurs lignes (deux blocs) dans Vim

Je tiens à fusionner les deux blocs de lignes dans Vim, c'est-à-dire prendre les lignes et ajouter à lignes . Si vous préférez une explication du pseudo-code :``

Exemple :

devrait devenir

Y a-t-il une bonne façon de faire cela sans faire copier/coller manuellement ?

885voto

rampion Points 38697

Vous pouvez certainement faire tout cela avec un simple copier/coller (à l'aide de bloc-mode de sélection), mais je suppose que c'est pas ce que vous voulez.

Si vous voulez le faire avec Ex - commandes

:5,8del | let l=split(@") | 1,4s/$/\=remove(l,0)/

transformera

work it 
make it 
do it 
makes us 
harder
better
faster
stronger
~

en

work it harder
make it better
do it faster
makes us stronger
~

Mise à JOUR: Une réponse avec ce nombre d'upvotes mérite une explication plus approfondie.

Dans Vim, vous pouvez utiliser le caractère pipe (|) chaîner les commandes Ex, de sorte que le ci-dessus est équivalente à

:5,8del
:let l=split(@")
:1,4s/$/\=remove(l,0)/

De nombreux Ex-commandes accepter une gamme de lignes comme préfixe de l'argument dans le cas ci-dessus l' 5,8 avant l' del et de la 1,4 avant l' s/// de spécifier les lignes de commandes opérer.

del supprime les lignes donnée. Il peut prendre un registre argument, mais quand on n'est pas donnée, elle exporte les lignes pour le registre sans nom, @", tout comme la suppression en mode normal. let l=split(@") se sépare ensuite les lignes supprimées dans la liste, en utilisant le délimiteur par défaut: les espaces blancs. Pour travailler correctement sur l'entrée qui avait espaces dans les lignes supprimées, comme:

more than 
hour 
our 
never 
ever
after
work is
over
~

nous aurions besoin de spécifier un autre séparateur, pour éviter "le travail est" d'être scindé en deux éléments d'une liste: let l=split(@","\n").

Enfin, dans la substitution s/$/\=remove(l,0)/, nous remplaçons la fin de chaque ligne ($) avec la valeur de l'expression remove(l,0). remove(l,0) modifie la liste l, la suppression et le retour de son premier élément. Cela nous permet de remplacer les lignes supprimées dans l'ordre dans lequel nous les lisons. Nous avons pu, au lieu de remplacer les lignes supprimées dans l'ordre inverse en utilisant remove(l,-1).

58voto

ib. Points 14520

Un élégant et concis commande Ex résoudre le problème qui peut être obtenu par combinant l' :global, :move, et :join des commandes. En supposant que le premier bloc de lignes qui commence sur la première ligne de la mémoire tampon, et que le le curseur se trouve sur la ligne qui précède immédiatement la première ligne de la deuxième bloc, la commande est la suivante.

:1,g/^/''+m.|-j!

Pour une explication détaillée de la technique utilisée, voir la réponse que j'ai donné à à la question "Vim collez -d '' le comportement de la boîte?".

45voto

mliebelt Points 9534

Pour rejoindre les blocs de la ligne, vous devez faire les étapes suivantes:

  1. Aller à la troisième ligne: jj
  2. Entrez visuel en mode bloc: CTRL-v
  3. Ancre le curseur à la fin de la ligne (important pour les lignes de longueurs différentes): $
  4. Aller à la fin: CTRL-END
  5. Couper le bloc: x
  6. Aller à la fin de la première ligne: kk$
  7. Coller le bloc ici: p

Le mouvement n'est pas le meilleur (je ne suis pas un expert), mais ça fonctionne comme tu le voulais. Espérons qu'il y aura une version plus courte.

Voici les prerequisits si cette technique fonctionne bien:

  • Toutes les lignes du bloc de départ (dans l'exemple de la question, abc et def) ont la même longueur XOR
  • la première ligne du bloc de départ est la plus longue, et vous ne se soucient pas de l'espace supplémentaire entre les deux) XOR
  • La première ligne du bloc de départ n'est pas la plus longue, et des espaces à la fin.

19voto

Voici comment je le ferais (avec le curseur sur la première ligne):

qama:5<CR>y$'a$p:5<CR>dd'ajq3@a

Vous avez besoin de savoir deux choses:

  • Le numéro de la ligne sur laquelle la première ligne du deuxième groupe commence (5 dans mon cas), et
  • le nombre de lignes dans chaque groupe (3 dans mon exemple).

Voici ce qu'il se passe:

  • qa enregistre tout, jusqu'à la prochaine q dans une "zone tampon" en a.
  • ma crée une marque sur la ligne actuelle.
  • :5<CR> passe au groupe suivant.
  • y$ ramène le reste de la ligne.
  • 'a revient à la marque, définie précédemment.
  • $p pâtes à la fin de la ligne.
  • :5<CR> renvoie le deuxième groupe de la première ligne.
  • dd le supprime.
  • 'a revient à la marque.
  • jq descend d'une ligne, et arrête l'enregistrement.
  • 3@a répète l'action pour chaque ligne (3 dans mon cas)

8voto

kevinlawler Points 451

Comme mentionné ailleurs, sélection de bloc est le chemin à parcourir. Mais vous pouvez également utiliser n’importe quelle variante de :

``

Cette méthode s’appuie sur la ligne de commande UNIX. Le `` utilitaire a été créée pour gérer ce genre de fusion de la ligne.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X