Ich möchte zwei Zeilenblöcke in Vim zusammenführen, dh Zeilen nehmen n..m
und an Zeilen anhängen a..b
. Wenn Sie eine Pseudocode-Erklärung bevorzugen:[a[i] + b[i] for i in min(len(a), len(b))]
Beispiel:
abc
def
...
123
45
...
soll werden
abc123
def45
Gibt es eine gute Möglichkeit, dies zu tun, ohne manuell kopieren und einfügen zu müssen?
x
mit Join verbindenx+2
?[a[i] + b[i] for i in min(len(a), len(b))]
Antworten:
Sie können dies sicherlich alles mit einem einzigen Kopieren / Einfügen (unter Verwendung der Blockmodus-Auswahl) tun, aber ich vermute, das ist nicht das, was Sie wollen.
Wenn Sie dies nur mit Ex- Befehlen tun möchten
wird sich verwandeln
in
UPDATE: Eine Antwort mit so vielen positiven Stimmen verdient eine gründlichere Erklärung.
In Vim können Sie das Pipe-Zeichen (
|
) verwenden, um mehrere Ex-Befehle zu verkettenViele Ex-Befehle akzeptieren einen Zeilenbereich als Präfixargument - im obigen Fall geben die
5,8
vordel
und1,4
vor dens///
Zeilen an, auf welchen Zeilen die Befehle ausgeführt werden.del
löscht die angegebenen Zeilen. Es kann ein Registerargument annehmen, aber wenn eines nicht angegeben wird, werden die Zeilen in das unbenannte Register@"
verschoben, genau wie beim Löschen im normalen Modus.let l=split(@")
teilt dann die gelöschten Zeilen unter Verwendung des Standardtrennzeichens: Leerzeichen in eine Liste auf. So arbeiten Sie ordnungsgemäß an Eingaben mit Leerzeichen in den gelöschten Zeilen:Wir müssten ein anderes Trennzeichen angeben, um zu verhindern, dass "work is" in zwei Listenelemente aufgeteilt wird :
let l=split(@","\n")
.Schließlich
s/$/\=remove(l,0)/
ersetzen wir bei der Ersetzung das Ende jeder Zeile ($
) durch den Wert des Ausdrucksremove(l,0)
.remove(l,0)
Ändert die Listel
, löscht das erste Element und gibt es zurück. Auf diese Weise können wir die gelöschten Zeilen in der Reihenfolge ersetzen, in der wir sie gelesen haben. Wir könnten stattdessen die gelöschten Zeilen in umgekehrter Reihenfolge durch verwendenremove(l,-1)
.quelle
s/\s*$/
anstelle von entfernens/$/
.:sil5,8del | let l=split(@") | sil1,4s/$/\=remove(l,0)/ | call histdel("/", -1) | nohls
scheint noch besser zu sein, da es den Suchverlauf nach dem Ausführen bereinigt. Und es wird nicht die Meldung "x mehr / weniger Zeilen" angezeigt, bei der ich die Eingabetaste drücken muss.:help range
,:help :d
,:help :let
,:help split()
,:help :s
,:help :s\=
,:help remove()
.Ein eleganter und prägnanter Ex Befehl das Problem lösen kann , indem die erhalten wird
:global
,:move
und:join
Befehle. Unter der Annahme, dass der erste Zeilenblock in der ersten Zeile des Puffers beginnt und sich der Cursor in der Zeile unmittelbar vor der ersten Zeile des zweiten Blocks befindet, lautet der Befehl wie folgt.Eine ausführliche Erläuterung dieser Technik finden Sie in meiner Antwort auf eine ähnliche Frage: " Vim paste -d" Verhalten sofort einsatzbereit? ”.
quelle
E16: Invalid Range
- aber es funktioniert trotzdem. Beim Entfernen1,
funktioniert es ohne den Fehler.:move
und:join!
, noch was''
als Bereichsargument (:help ''
) und was+
und-
als Bereichsmodifikatoren (:help range
) bedeutete. Vielen Dank!sil!
man dem Befehl voranstellt .Um Linienblöcke zu verbinden, müssen Sie die folgenden Schritte ausführen:
jj
CTRL-v
$
CTRL-END
x
kk$
p
Die Bewegung ist nicht die beste (ich bin kein Experte), aber sie funktioniert so, wie Sie es wollten. Hoffe, es wird eine kürzere Version davon geben.
Hier sind die Voraussetzungen, damit diese Technik gut funktioniert:
abc
unddef
) haben die gleiche Länge XORquelle
abc
unddef
sind gleich lang. Bei der Blockauswahl bleiben die Einrückungen des gelöschten Texts erhalten. Wenn sich der Cursor beim Einfügen des Texts in einer kurzen Zeile befindet, werden die Zeilen zwischen den Buchstaben der längeren eingefügt - und Leerzeichen an die kürzeren, wenn sich der Cursor auf einer längeren befindet einer.:%s/ \+/ /g
set ve=all
sollte helfen, siehe vimdoc.sourceforge.net/htmldoc/options.html#'virtualedit 'So würde ich es machen (mit dem Cursor in der ersten Zeile):
Sie müssen zwei Dinge wissen:
Folgendes ist los:
qa
zeichnet alles bis zum nächstenq
in einem "Puffer" aufa
.ma
Erstellt eine Markierung in der aktuellen Zeile.:5<CR>
geht zur nächsten Gruppe.y$
reißt den Rest der Linie.'a
kehrt zur zuvor eingestellten Marke zurück.$p
Pasten am Ende der Linie.:5<CR>
kehrt zur ersten Zeile der zweiten Gruppe zurück.dd
löscht es.'a
kehrt zur Marke zurück.jq
geht eine Zeile runter und stoppt die Aufnahme.3@a
wiederholt die Aktion für jede Zeile (3 in meinem Fall)quelle
[Enter]
nach:5
beiden Eingaben drücken, sonst funktioniert dies nicht.:norm qama:5<CR>y$'a$p:5<CR>dd'ajq3@a
aber das scheint nur auszuführenq
.:let @a="ma:5^My$'a$p:5^Mdd'aj" | normal 4@a
, die^M
Zeichen einzugeben , indem Sie STRG -V und dann die Eingabetaste drücken .Wie an anderer Stelle erwähnt, ist die Blockauswahl der richtige Weg. Sie können aber auch eine beliebige Variante verwenden:
:!tail -n -6 % | paste -d '\0' % - | head -n 5
Diese Methode basiert auf der UNIX-Befehlszeile. Das
paste
Dienstprogramm wurde für diese Art der Linienzusammenführung erstellt.quelle
paste -d
ähnliche) Verhalten kann mit einem kurzen Vim-Befehl implementiert werden, wie in meiner Antwort gezeigt .Die Beispieldaten sind die gleichen wie bei Rampion.
quelle
Ich würde es nicht zu kompliziert machen. Ich würde einfach virtualedit auf
(
:set virtualedit=all
) setzen.Wählen Sie Block 123 und alle unten.
Setzen Sie es nach der ersten Spalte:
und entfernen Sie das Mehrfachzeichen zwischen 1 Leerzeichen:
quelle
gvV:'<,'>s/\s+//g
(vim sollte das automatisch'<,'>
für Sie einfügen , damit Sie es nicht manuell eingeben müssen).Ich würde komplexe Wiederholungen verwenden :)
Angesichts dessen:
Drücken Sie mit dem Cursor in der ersten Zeile Folgendes:
und drücken
@a
Sie dann@@
so oft wie nötig (und Sie können es anschließend verwenden ).Sie sollten am Ende haben mit:
(Plus eine neue Zeile.)
Erklärung:
qa
Startet die Aufnahme einer komplexen Wiederholung ina
}
springt zur nächsten leeren Zeilejdd
löscht die nächste Zeile''
kehrt zur Position vor dem letzten Sprung zurückp
Fügen Sie die gelöschte Zeile unter der aktuellen einkJ
Fügen Sie die aktuelle Zeile an das Ende der vorherigen Zeile anx
Löschen Sie den AbstandJ
zwischen den kombinierten Zeilen. Sie können dies weglassen, wenn Sie den Platz möchtenj
gehe zur nächsten Zeileq
Beenden Sie die komplexe WiederholungsaufnahmeDanach können Sie die
@a
in gespeicherte komplexe Wiederholung ausführena
und anschließend@@
die zuletzt ausgeführte komplexe Wiederholung erneut ausführen .quelle
Es gibt viele Möglichkeiten, dies zu erreichen. Ich werde zwei Textblöcke mit einer der beiden folgenden Methoden zusammenführen.
Angenommen, der erste Block befindet sich in Zeile 1 und der zweite Block beginnt in Zeile 10 mit der Anfangsposition des Cursors in Zeile 1.
(\ n bedeutet das Drücken der Eingabetaste.)
mit einem Makro mit den Befehlen: Kopieren, Einfügen und Verbinden.
Verschieben Sie mit einem Makro mithilfe der Befehle eine Zeile an der n-ten Zeilennummer und verbinden Sie sie.
quelle