Je voudrais fusionner deux blocs de lignes dans Vim, c’est-à-dire prendre les lignes n..m
et les append aux lignes a..b
. Si vous préférez une explication de pseudocode: [a[i] + b[i] for i in min(len(a), len(b))]
Exemple:
abc def ... 123 45 ...
devraient devenir
abc123 def45
Existe-t-il un bon moyen de le faire sans copier-coller manuellement?
Vous pouvez certainement faire tout cela avec un seul copier / coller (en utilisant la sélection en mode bloc), mais je suppose que ce n’est pas ce que vous voulez.
Si vous voulez faire cela avec juste des commandes Ex
:5,8del | let l=split(@") | 1,4s/$/\=remove(l,0)/
va transformer
work it make it do it makes us harder better faster stronger ~
dans
work it harder make it better do it faster makes us stronger ~
MISE À JOUR: Une réponse à ces nombreuses citations mérite une explication plus approfondie.
Dans Vim, vous pouvez utiliser le caractère pipe ( |
) pour enchaîner plusieurs commandes Ex, ce qui équivaut à
:5,8del :let l=split(@") :1,4s/$/\=remove(l,0)/
De nombreuses commandes Ex acceptent une plage de lignes comme argument de préfixe – dans le cas ci-dessus, le 5,8
avant le del
et le 1,4
avant le s///
spécifient les lignes sur lesquelles les commandes opèrent.
del
supprime les lignes données. Il peut prendre un argument de registre, mais quand on ne le donne pas, il vide les lignes dans le registre sans nom, @"
, comme le fait la suppression en mode normal. let l=split(@")
puis divise les lignes supprimées , en utilisant le délimiteur par défaut: blanc. Pour travailler correctement sur une entrée comportant des espaces dans les lignes supprimées, comme:
more than hour our never ever after work is over ~
nous aurions besoin de spécifier un séparateur différent, pour éviter que “work is” ne soit divisé en deux éléments de liste: let l=split(@","\n")
.
Enfin, dans la substitution s/$/\=remove(l,0)/
, nous remplaçons la fin de chaque ligne ( $
) par la valeur de l’expression remove(l,0)
. remove(l,0)
modifie la liste l
, en supprimant et en renvoyant son premier élément. Cela nous permet de remplacer les lignes supprimées dans l’ordre dans lequel nous les lisons. Nous pourrions remplacer les lignes supprimées dans l’ordre inverse en utilisant remove(l,-1)
.
Une commande élégante et concise de résolution des problèmes peut être obtenue en combinant les commandes :global
:move
et :join
. En supposant que le premier bloc de lignes commence sur la première ligne du tampon et que le curseur se trouve sur la ligne précédant immédiatement la première ligne du 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ée à la question ” Vim paste -d” comportement hors de la boîte? “.
Pour joindre des blocs de ligne, vous devez suivre les étapes suivantes:
jj
CTRL-v
$
CTRL-END
x
kk$
p
Le mouvement n’est pas le meilleur (je ne suis pas un expert), mais cela fonctionne comme vous le souhaitiez. J’espère qu’il y aura une version plus courte de celui-ci.
Voici les prérequirejs pour que cette technique fonctionne bien:
abc
et def
) ont la même longueur XOR Voici comment je le ferais (avec le curseur sur la première ligne):
qama:5y$'a$p:5 dd'ajq3@a
Vous devez savoir deux choses:
Voici ce qui se passe:
qa
enregistre tout jusqu’au q
suivant dans un “tampon” dans a
. ma
crée une marque sur la ligne en cours. :5
va au groupe suivant. y$
tire le rest de la ligne. 'a
retour à la marque, défini plus tôt. $p
à la fin de la ligne. :5
revient à la première ligne du deuxième groupe. dd
supprime. 'a
retour à 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) Comme mentionné ailleurs, la sélection de blocs est la voie à suivre. Mais vous pouvez également utiliser n’importe quelle variante de:
:!tail -n -6 % | paste -d '\0' % - | head -n 5
Cette méthode repose sur la ligne de commande UNIX. L’utilitaire de collage a été créé pour gérer ce type de fusion de lignes.
PASTE(1) BSD General Commands Manual PASTE(1) NAME paste -- merge corresponding or subsequent lines of files SYNOPSIS paste [-s] [-d list] file ... DESCRIPTION The paste utility concatenates the corresponding lines of the given input files, replacing all but the last file's newline characters with a single tab character, and writes the resulting lines to standard output. If end-of-file is reached on an input file while other input files still contain data, the file is treated as if it were an endless source of empty lines.
Les données de l’échantillon sont les mêmes que celles des rampions.
:1,4s/$/\=getline(line('.')+4)/ | 5,8d
Je ne pense pas que ce soit trop compliqué. Je voudrais juste mettre virtualedit sur
( :set virtualedit=all
)
Sélectionnez le bloc 123 et tous les suivants.
Mettez-le après la première colonne:
abc 123 def 45 ... ...
et supprimez l’espace multiple entre 1 espace:
:%s/\s\{2,}/ /g
J’utiliserais des répétitions complexes 🙂
Compte tenu de ceci:
aaa bbb ccc AAA BBB CCC
Avec le curseur sur le premier “a” de la première ligne, appuyez sur le bouton suivant:
qq}jdd''$pkJj0q
puis appuyez sur @q
(et vous pourrez ensuite utiliser @@
) autant de fois que nécessaire.
Vous devriez vous retrouver avec:
aaaAAA bbbBBB cccCCC
(Plus une nouvelle ligne.)
Il peut y avoir de nombreuses façons d’y parvenir. Je vais fusionner deux blocs de texte en utilisant l’une des deux méthodes suivantes.
supposons que le premier bloc se trouve à la ligne 1 et que le deuxième bloc commence à la ligne 10 avec la position initiale du curseur au numéro de ligne 1.
(\ n signifie appuyer sur la touche Entrée.)
1. abc def ghi 10. 123 456 789
avec une macro en utilisant les commandes: copier, coller et joindre.
qaqqa: + 9y \ npkJjq2 @ a10G3dd
avec une macro utilisant les commandes, déplacez une ligne au nième numéro de ligne et rejoignez-la.
qcqqc: 10m. \ nkJjq2 @ c