Vim: Ersetzen einer Linie durch eine andere, die zuvor gezogen wurde

111

Mindestens einmal am Tag habe ich folgende Situation:

A: This line should also replace line X
...
X: This is line should be replaced

Ich glaube, dass ich diese Aufgabe nicht effizient erledige.

Was ich mache:

  • Gehen Sie zu Zeile A: AG
  • Rucklinie A: yy
  • Gehen Sie zu Zeile X: XG
  • Zeile A einfügen: P.
  • Zur alten Zeile wechseln : j
  • Alte Zeile löschen : dd

Dies hat den zusätzlichen Nachteil , dass Linie X jetzt im Standard - Register ist, was ärgerlich ist , wenn ich eine andere Linie finden , die mit A. Yanking zu und Einfügen von einem zusätzlichen Register (ersetzt werden sollten „ayy , “ aP ) macht diese einfache Aufgabe , auch weniger effizient.

Meine Fragen:

  • Habe ich einen eingebauten Vim-Befehl verpasst, um eine zuvor gezogene Linie zu ersetzen?
  • Wenn nicht, wie kann ich meinen eigenen Befehl binden, der die gezogene Zeile im Standardregister belässt (oder wiederherstellt)?
knusprig
quelle
2
Dies ist mein größtes Problem mit dem Bearbeitungsmodell von Vim. Ich würde gerne eine Lösung kennen. Ein CUA-Editor unterscheidet zwischen Ausschneiden und Löschen. Sie schneiden also nur Text aus und können dann alles, was Sie möchten, löschen und einfügen. Mit Vim werden alle von Ihnen vorgenommenen Löschvorgänge in den ausgeschnittenen Text verworfen. Am Ende verwenden Sie weit mehr Tastenanschläge als bei einem anderen Editor.
Schlamm
3
YankRing
Ajreal
@ Schlamm lernen über :moveund das Schwarze Loch Register ( _) (oder in der Tat nur Register)
sehe
2
@sehe Ich bin mir der Register durchaus bewusst, aber das fügt 4 Tastenanschläge pro Ausschneide- / Einfügevorgang hinzu und erfordert mehr Voraussicht. Wenn Sie viel bearbeiten, summiert sich das schnell.
Schlamm
Gibt es neben der Einsparung einiger Bytes Speicher einen Vorteil bei der Verwendung des Schwarzlochregisters im Gegensatz zu anderen Registern? Ich würde argumentieren, dass jedes Register ein Schwarzes Loch-Register sein kann, wenn Sie nicht daraus zurücklesen.
Sleblanc

Antworten:

91

Was ich tun würde :

  1. aG
  2. Y
  3. xG
  4. Vp

Sie müssen nicht normalen Modus verlassen, aber es tut yank die Linie. Sie können jedoch verwenden, V"0pwodurch die in Schritt 2 gezogene Linie immer gezogen wird.

Eiskriminalität
quelle
11
@ Duddle: Ja, Yist ein Synonym füryy
Eiskriminalität
8
Die Schritte 1 und 2 können kombiniert werden mit: ay [zB: 20y] Gefolgt von Vp sollte den Trick machen. Sie müssen nicht zu einer Linie gehen, um sie zu ziehen.
Bharad
2
Wenn Sie zusätzliche Zeilen mit ccCTRL + r0ESC anstelle von V "0p überschreiben, können alle folgenden Zeilen durch just ersetzt werden (der Repeater)
Jordan Morris
Yist ein Synonym für yy, aber ich schlage vor, es neu zuzuordnen, um y$zu Dund zu passen C.
mgold
Schauen Sie sich die Antwort von Jordan Morris an. Stackoverflow.com/users/970673/jordan-morris unten - verwendet vim-Befehle in vollem Umfang, indem Sie den Befehl mehrmals wiederholen können.
JESii
104

Vp: Linie auswählen, einfügen, was gezogen wurde

Dorian
quelle
3
VPfunktioniert genauso gut, was praktisch ist, da Sie die Umschalttaste für die gesamte Sequenz gedrückt halten können.
George Hilliard
23
Sehr netter Trick, obwohl es sich lohnt, eine (möglicherweise) erhebliche Einschränkung zu beachten: Dadurch wird das Ruckregister mit dem Inhalt der zu überschreibenden Zeile aktualisiert, sodass es bei einigen Aufgaben möglicherweise nicht gut funktioniert - z. B. wenn Sie überschreiben möchten die gleiche Linie auf mehrere Ziele.
underscore_d
8
@underscore_d, es spielt sich gut, wenn Sie dies tun V"0p, was aus dem zuletzt gezogenen Register eingefügt wird.
Timblaktu
@timblaktu Kannst du erklären, was V"0ptut? V wechselt in den visuellen Linienlinienmodus und p dient zum Einfügen. Wofür sind "und 0? Danke
theprogrammer
43

Dies hat den zusätzlichen Nachteil, dass sich Zeile X jetzt im Standardregister befindet, was ärgerlich ist, wenn ich eine andere Zeile finde, die durch A ersetzt werden sollte.

Um Text zu löschen, ohne die normalen Register zu beeinflussen, können Sie das Black-Hole-Register verwenden "_:

"_dd
Eugene Yarmash
quelle
10
Ich habe meiner .vimrc einige Zuordnungen hinzugefügt, um das Schwarze Loch zu erstellen dund ddimmer zu verwenden xund das xxauszuführen, was die meisten Editoren als "Ausschneiden" bezeichnen würden (Löschen und Speichern im Standardregister):noremap x d noremap xx dd noremap d "_d noremap dd "_dd
IMSoP
2
Ich bin vorsichtig, wenn es darum geht, Dinge in VIM neu zuzuordnen, da dies auf anderen Computern oder in Plugins im VIM-Stil für IDEs möglicherweise nicht einfach ist. Auch die Designer von VIM haben Probleme mit Standardzuordnungen gelöst, wenn Sie wirklich graben.
Jordan Morris
15

Aufbauend auf den Antworten, die die Verwendung Vpoder VPdas Einfügen über eine Linie vorschlagen - um zu vermeiden, dass der Inhalt des Ruckregisters geändert wird, finde ich den ergonomischsten Befehl einfach:

VPY

RichardW
quelle
Dies ist die einfachste Lösung, bei der der Ruckinhalt gleich bleibt. Danke vielmals!
Heylookltsme
14
  1. yy
  2. j (gehen Sie zu der Zeile, die Sie ersetzen möchten) und dann
  3. Vp (Großbuchstaben v und dann p werden durch den gezogenen Inhalt ersetzt)
Mariano Anaya
quelle
genial! Sehr kurz und macht es einfach, mehrere Zeilen im visuellen Modus auszuwählen. Außerdem bleibt der Pastenpuffer intakt. Es ist ärgerlich, wenn dd diesen Puffer überschreibt ...
Aktau
@Aktau dies lässt den Puffer nicht intakt.
Jordan Morris
9

Ich würde den Kommandozeilenmodus (Ex) verwenden und die folgenden zwei Befehle ausführen

:XmA
:Ad

Dadurch wird Zeile X einfach auf knapp unter A verschoben, und durch Löschen von A wird diese Zeile verschoben

Beispielsweise

:7m3
:3d
ericgamliel
quelle
Kannst du ein Beispiel geben? Wenn ich zB 50Gm30G drücke, geht Vim zu Zeile 50 und dann nach unten und das wars. Außerdem: Ad macht nichts für A = 50 oder A = 50G
knusprig
7
  1. Gehen Sie zum Anfang der ersten Zeile.

  2. y, $- Kopieren Sie die Zeile ohne Zeilenumbruch am Ende

  3. Gehen Sie zum Anfang der Ziellinie.

    1. V, p- nur eine Ziellinie ersetzen

    2. c, c, Ctrlr, 0, Esc- die Ziellinie mit dem ursprünglichen Ruck ersetzen

  4. Gehen Sie zum Anfang der nächsten Ziellinie.

  5. . - wiederholt den bei 4.2 ausgegebenen Befehl.

Anmerkungen:

  • 4.1 ist y, $denn wenn Sie das tun y, yoder YSie werden die Zeilenumbrüche kopieren, und Ctrlr0tatsächlich den Zeilenumbruch unterhalb Ihrer Ziellinie ergänzt.

  • 4.2 ersetzt V p, was bei Wiederholung nicht funktioniert, da technisch gesehen die letzte Aktion Löschen ist, also .nur eine Zeile löschen würde.

  • Wenn jemand weiß, wie man im EX-Modus (Befehlszeile) "Aktuelle Zeile durch Register ersetzen" ausgibt, würde ich gerne von Ihnen hören (und wissen, wo Sie die Dokumentation gefunden haben). Möglicherweise gibt es einen wiederholbaren EX-Befehl, der schneller als 4.2 ist und / oder nicht die Einschränkung für Zeilenumbrüche enthält.

Jordan Morris
quelle
1
Schritt 4.2 ist hier der Killer, da Sie jetzt den gesamten Vorgang mit dem Punktbefehl wie in 4.3 wiederholen können - darum geht es bei vim!
JESii
1
Ich verstehe das nicht. 'AG' setzt meinen Maker an das Ende der Zeile, wechselt in den Einfügemodus und gibt ein 'G' ein. Was bekomme ich nicht?
Gustafbstrom
@gustafbstrom faire Kritik - Entschuldigung, das A sollte die Zeilennummer darstellen, aber ich habe nicht darauf hingewiesen. Bearbeitet.
Jordan Morris
5

Folgendes würde ich tun

  • Verschieben Sie den Anfang von Zeile A AG(wobei A offensichtlich eine Zeilennummer ist).
  • Ziehen Sie die Leitung an ein Register, z. B. a (ohne neue Zeile). Art"ay$
  • Zum Einfügen einer Zeile bewegen, XG
  • Ersatzlinie, S
  • Einfügen aus Register a, Ctrl-Ra
Brian Rasmussen
quelle
4

Sie können dies im visuellen Modus verwenden.

  • Gehen Sie zu Zeile A: AG
  • Wählen Sie die Linie mit visuellem Modus: VESC
  • gehe zu Zeile X: XG
  • Aktivieren Sie den Ersatzmodus für die Zeile: S
  • Fügen Sie die kopierte Zeile ein: shift+ insert(oder eine andere Zuordnung, die Sie zum Einfügen aus der Zwischenablage haben).
Nathan Fellman
quelle
Ah. Wusste nicht über V und S . Ihre Schritte funktionieren jedoch nicht für mich, da ich nicht in meine Zwischenablage des Betriebssystems ziehe, die die einzige ist, auf die ich im Einfügemodus zugreifen kann. Also müsste ich zuerst den Einfügemodus verlassen.
knusprig
3

Sie können auch tun:

Vy (in normal mode at the line you want to copy)
Vp (in normal mode at the line you want to replace)
  • Erstellt keine Leerzeichen oder Zeilenenden.
  • Der Cursor befindet sich am Anfang des kopierten Textes.

Mit denselben Tasten können Sie mehr als eine Zeile ziehen / einfügen.

V (in normal mode at what you want to yank)
(use jk to move the selection)
y (to yank the selection)
V (in normal mode at where you want to paste)
(use jk to move the selection)
p (to replace the selection with the yanked lines)
Kozmonaut
quelle
2

Sie können diese Befehle im normalen Modus verwenden:

:AmX | Xd

Der mBefehl ist für m[ove], der die Zeilennummer A nach der Zeilennummer X verschiebt. Wenn Sie kopieren möchten, anstatt die Zeile zu verschieben, verwenden Sie co[py]. Der dBefehl ist für d[elete].

Sie können coeine Reihe von Zeilen mit verschieben (kopieren mit )

:start,end m X
Nafaa Boutefer
quelle
2

Angesichts des jüngsten Kommentars von cicld (danke!) Sehe ich, dass ich das ursprüngliche Problem nicht vollständig verstanden habe. Das Verschieben der Zeile ist nicht angemessen, das Kopieren jedoch (da die Zeile gezogen wird). Daher würde ich sie überarbeiten, um:

:1t20:20d_
  1. Kopieren Sie die erste Zeile ( :tBefehl ist ein Alias ​​für :copy) nach Zeile 20 (wird in Zeile 21 platziert)

  2. Löschen Sie Zeile 20 und legen Sie die gelöschte Zeile in das 'Blackhole'-Register ( _) (dh ohne Einfluss auf den aktuellen Ruck-Puffer).

Wie im letzten Kommentar erwähnt, hat dies keine Auswirkungen auf die aktuelle Cursorposition.

nkalvi
quelle
1
  1. : ay (wobei a die Zeilennummer ist. Beispiel: 20y). Dies reißt eine Linie (Wortspiel beabsichtigt).
  2. Vp
Bharad
quelle
1

Ich finde es einfacher, den Befehl Ex dafür zu verwenden. Ex. Zeile 9 bis 46 verschieben:

 :46|9m.|-1d

Dadurch wird der Cursor auf Zeile 46 bewegt, Zeile 9 unter die aktuelle Zeile verschoben und dann die vorherige Zeile gelöscht (da die verschobene Zeile die aktuelle Zeile ist).

Oder mit Markierung (en), mit Markierung 'a':

:46ma a|9m'a|'ad
nk3181544
quelle
Das Schöne an EX-Befehlen ist, dass Sie sie überall dort ausführen können, wo sich Ihr Cursor befindet (im normalen Modus). Ich bevorzuge :1m20|.+1d(Zeile 1 in Zeile 20 verschieben und die nächste Zeile löschen, dh Text, der zuvor in Zeile 20 stand). Gleiche Idee!
Circld
1

Ich muss oft eine Zeile Y und sie an mehreren Stellen ersetzen, von denen jede einen anderen Wert hat (was bedeutet, dass ich keinen regulären Ausdruck machen kann).

Y die gewünschte ursprüngliche Linie ziehen

und dann in jeder Zeile, die Sie ersetzen möchten, VpzeroY

Ron
quelle
0

Ich würde einfach das "Black Hole" -Register verwenden:

gegeben:

nnoremap <Cd> "_dd

Die Lösung wäre:

<Cd> yy

j5shi
quelle