Wie lösche ich einen großen Textblock, ohne die Zeilen zu zählen?


91

In vim muss ich oft große Textblöcke löschen oder reißen / setzen.

Ich kann die Textzeilen zählen und so etwas wie 50dd50 Zeilen löschen.

Aber das ist ein bisschen schmerzhaft. Wie kann ich diesen großen Textblock löschen, ohne vorher wissen zu müssen, wie viele Zeilen gelöscht werden sollen?


4
Woher weißt du, wo das Ende ist? Wenn Sie das Ende beschreiben können, können Sie bis zu diesem Punkt löschen. Wenn Sie beschreiben können, wie Sie movebis zum Ende können. Dann ist das Löschen bis zum Ende nicht anders als das Verschieben bis zum Ende.
Martin York

@Loki, um ans Ende zu gelangen, brauche ich normalerweise nur die Bild-ab-Taste und die Pfeiltasten, bis ich dort bin. Es kann sich um die erste oder zehnte Leerzeile handeln, es kann sich um die erste schließende Klammer handeln. Unterm Strich ist es ziemlich unterschiedlich.

2
Überprüfen Sie auch diese Antwort: stackoverflow.com/a/16407391/164835
Kent

Antworten:


111

Gehen Sie zur Anfangszeile Ihres Blocks und geben Sie ein ma(markieren Sie "a", obwohl Sie natürlich auch verschiedene Buchstaben und sogar mehrere Buchstaben für verschiedene Markierungen verwenden können, vorausgesetzt, Sie können es in Ihrem Kopf gerade halten, wovon jeder Buchstabe eine Marke ist) .

Gehen Sie dann in die letzte Zeile und geben Sie d'a(Löschen, um "a" zu markieren) oder y'a(Ziehen, um "a" zu markieren) (a) ein .

Dadurch werden alle Zeilen von der aktuellen bis zur markierten Zeile (einschließlich) gelöscht / entfernt.

Dann können Sie es mit den normalen Einfügebefehlen wie poder an einer anderen Stelle einfügen P.

Es ist auch kompatibel mit viund vim, falls Ihre Umgebung nicht mit letzterem gesegnet ist.


(a) Ich verwende dies auch, um meinen Platz in der Datei zu speichern, wenn ich nach etwas anderem suchen muss, zum Beispiel nach dem Einfügen der Definition einer Funktion, die ich aufrufen möchte.

Ich markiere einfach die aktuelle Zeile auf die gleiche Weise und magehe dann los, um zu finden, wonach Sie suchen.

Sobald ich es gefunden und in ein Register kopiert habe, 'agehe ich zurück und markiere "a", die zuvor gespeicherte Zeile, wo ich es dann einfügen kann.


9
Könnte man dafür auch den visuellen Modus verwenden, oder?
jmc

3
Das ist eine Möglichkeit, jmc, aber ich bin mir nicht sicher, ob Standard vi einen visuellen Modus hat.

5
Seit ich vor ungefähr einem Jahr von der visuellen Auswahl zur Markierung und zu den relativen Zeilennummern übergegangen bin, habe ich festgestellt, dass vi-Bewegungsbefehle viel schneller und effizienter sind als die visuelle Auswahl. Auch wenn das spätere jedes Mal einfacher ist, wenn ich die vTaste drücke, frage ich mich, ob ich es wirklich brauche oder ob es einen besseren Bewegungsweg gibt.
Sukima,

1
Ja, auf die gleiche Weise ist es interessant, @Sukima, dass ich mich effizienter fühle, je weniger ich die Maus benutze, auch in einer GUI. Ich bin schneller, wenn ich auf der Tastatur bleiben kann.

3
Wenn Sie jemals etwas mit sehr langen Zeilen bearbeiten, kann die Backtick-Version auch sehr nützlich sein (bezieht sich auf die Stelle innerhalb der Zeile und nicht auf die gesamte Zeile).
Msouth

65

Verwenden Sie in Vim den visuellen Linienmodus :

  1. Setzen Sie den Cursor auf die oberste Zeile des zu entfernenden Text- / Codeblocks
  2. Drücken Sie V(das ist die Hauptstadt "V": Shift+ v)
  3. Bewegen Sie den Cursor an den unteren Rand des zu entfernenden Text- / Codeblocks
  4. Drücken Sie d

Zum Löschen großer Textblöcke ist dies dem einfachen visuellen Modus vorzuziehen, da Sie sich keine Gedanken darüber machen müssen, auf welcher Spalte sich der Cursor befindet.


3
In Schritt 3 können Sie sich mit Objektbewegungen schneller bewegen. Zum Beispiel kann }mit ganzen Absatz oder )für Sätze ausgewählt werden. Es gibt noch mehr, die könnt ihr in:h object-motions
mxlian

2
Auch die Suche nach einem Teilstring mit /something<CR>ist eine sehr effiziente Methode, um das Ende Ihres Auswahlblocks zu erreichen
mxlian

1
Dies ist meine bevorzugte Methode. Alternativ können jSie auch die Zeilennummer eingeben, ohne wiederholt drücken zu müssen, um den Cursor nach unten zu bewegen (Schritt 3). Anschließend können GSie bis zu dieser Zeile auswählen. Beispiel:V150Gd
Ranhiru Jude Cooray


39

Sie können problemlos große Textblöcke löschen, wenn Sie die Struktur kennen.

Wenn es sich um einen Absatz handelt, verwenden Sie: d{(Sie können z. B. die Anzahl der Absätze voranstellen)

Wenn es sich um einen Codeblock in Klammern handelt, verwenden Sie: d%

Wenn der Text bis zum Ende der Datei erscheint, verwenden Sie: dG

Wenn Sie wissen, wie es endet, verwenden Sie: d/und geben Sie den Endtext gefolgt von ein Enter(Sie können auch reguläre Ausdrücke verwenden, sodass die Möglichkeiten endlos sind).

Verwenden Sie alternativ den visuellen Modus ( V) und die Bewegungstasten, um den Text schnell auszuwählen (z. B. durch {) und zu entfernen ( d).

Oder verwenden Sie, wie Lie Ryan vorgeschlagen hat d/search-string/e, um Text aus dem aktuellen Cursor in die gesuchte Zeichenfolge zu löschen.

Siehe: :help dund :help motionfür mehr Infos.


2
Es besteht auch d/search-string/edie Möglichkeit, vom aktuellen Cursor bis zum Ende des Suchstrings einschließlich des Suchstrings selbst zu löschen und c/search-querynach dem Löschen in den Einfügemodus zu gelangen. Die Verwendung von d/with set incsearchist eine übersichtliche Kombination, mit der Sie interaktiv herausfinden können, ob Sie im richtigen Textbereich arbeiten, und Sie wissen, wann Sie mit der Eingabe der Suchabfrage aufhören müssen, um zu vermeiden, dass Sie mehr als nötig eingeben.
Lie Ryan

4
Ich finde auch dmit a(äußerlich) oder i(innerlich) und einem Objektbezeichner sehr nützlich. Objekte wie wfür Wort, pfür Absatz, (oder bfür (...), [für [...], {oder Bfür {...}usw. Dokumentation für Visual-Betreiber .
Shahbaz,

22

Sie können Bewegungen und / oder Textobjekte verwenden. Zum Beispiel können Sie mit alles vom Cursor bis zur nächsten leeren Zeile löschen d}. Befindet sich der Cursor in einem Absatz, kann der Absatz mit dipoder gelöscht werden dap. Befindet sich der Cursor innerhalb eines HTML-Tags, können Sie ihn mit ditoder löschen dat.

Gute Mnemoniken für diese sind " d elete i nside" und " d elete a round" (Absatz / Tag / Klammer).


11

Normalerweise mache ich

:<start>,<end>d

Dadurch wird jede Zeile zwischen den angegebenen Start- und Endzeilennummern (einschließlich der angegebenen Zeilen) gelöscht.

Beachten Sie, dass beides startund endabsolute Zeilennummern, Muster oder Versätze von einer anderen Position sein können.

Siehe auch Double Kommentar über das Anzeigen Vims Bereich Dokumentation, es einige nützliche Tipps hat.

Beispiel:

Angenommen, Sie haben die folgende Datei:

1. The quick brown
2. fox jumps
3. over the
4. lazy dog.

Wenn Sie dann den Befehl :2,3doder :/fox/,/over/doder :/quick/+1,/lazy/-1oder :+1,+2din der ersten Zeile oder :-1,.din der dritten Zeile verwenden, erhalten Sie:

1. The quick brown
4. lazy dog.

Aber das heißt, Sie müssen noch die Zeilen zählen? Oder habe ich deine Antwort falsch verstanden?
Martin Tournoij

7
Sie müssen die Zeilen nicht zählen, aber Sie müssen die Zeilennummern kennen.
Jmc

Zuerst tun :set ruler, dann nach oben und unten des Textes zu finden startund endZeilennummern, dann tun:<start>,<end>d
roblogic

1
Sie können auch relative Zeilennummern verwenden:+12,+24d
rpattabi

2
Eigentlich kann man ein Paar von Zeilennummern verwenden, ein Paar von Mustern oder gemischtes Paar für <start>und <end>für diesen. Referenz siehe :h [range]. Es ist also viel flexibler, als Sie es sich vorgestellt haben.
DoubleDown

5

Wenn es sich um begrenzte Blöcke handelt (z. B. Code oder XML / HTML-Tags), können Sie den Cursor an den Anfang des Blocks setzen und den visuellen Modus zusammen mit verwenden, %um schnell ganze Codeblöcke auszuwählen und dann zu drücken dum sie zu löschen.


5
Alternativ können Sie verwenden dapeinen Absatz löschen zu, da(, da{, da[, zu den Blöcken löschen delimeted durch Klammern, oder eckigen Klammern. Für HTML gibt es dat, die ein Tag löscht, und da'und da"Zeichenfolgen löschen. Es gibt auch die dip, di(usw Varianten, die alles in den Trennzeichen löschen, aber die Trennzeichen intakt lassen. Alternativ können Sie vap(resp vip) verwenden, um alle (resp inneren) Absätze auszuwählen. (Und so gibt es va(und vi(.) Weiter gibt es capund cip(oder ca(und ci() zum Löschen und zum Einfügen (dh "Ändern"). Und yapzum reißen
jmc

Ich denke, einige der Bindings @jmc, die in seinem früheren Kommentar beschrieben wurden, stammen aus dem surround.vim-Plugin von Tim Pope. Es ist ein großartiges Plugin, das ich empfehlen würde zu installieren, aber es bedeutet, dass diese Bindungen nicht Teil der vim-Standardinstallation sind.
Haegin

5

Neben all dem anderen guten Rat Ich füge d+ Shift+ Lfür auf dem Bildschirm alles von der aktuellen Cursorposition in die letzten sichtbaren Zeile zu löschen. Wenn Sie den Befehl wiederholen, werden Sie relativ schnell außer Gefecht gesetzt.


5

Das numbers.vim Plugin ist dafür sehr nützlich. Auf diese Weise können Sie jeder Zeile eine Zeilennummer voranstellen. Wie 'number'und 'relativenumber', beide haben sich zu einem zusammengerollt!

Es ist standardmäßig nach der Installation aktiviert. Sie möchten es auch set numberzu Ihrem vimrc hinzufügen , wenn Sie es noch nicht haben, da es sich auf seltsame Weise verhält, wenn Sie es nicht haben.

Im normalen Modus sieht es ungefähr so ​​aus :set relativenumber:

  3 call plug#begin('~/.vim/plugged')
  2 
  1 Plug 'myusuf3/numbers.vim'
7   set number█
  1 
  2 " Add indentation 'guidelines' (:IndentLinesToggle or <F11>)
  3 Plug 'Yggdroot/indentLine'

Hier werden relative Zeilennummern angezeigt, mit Ausnahme der Zeile, in der sich der Cursor befindet, und der absoluten Zeilennummer (in diesem Fall 7).

Wenn wir dann in den Einfügemodus wechseln , verhält es sich so, als ob numberimmer absolute Zeilennummern angezeigt würden:

  4 call plug#begin('~/.vim/plugged')
  5 
  6 Plug 'myusuf3/numbers.vim'
  7 set number█
  8   
  9 " Add indentation 'guidelines' (:IndentLinesToggle or <F11>)
 10 Plug 'Yggdroot/indentLine'

Es gibt einige weitere Optionen und einige Befehle (siehe Homepage), aber die Standardeinstellungen sollten für die meisten Leute funktionieren.


Zuerst dachte ich, diese Antwort sei ein bisschen unangebracht, aber dann habe ich das Plugin installiert und ich muss sagen, es ist ein Game Changer für mich. Früher habe ich manuell getauscht, und der zusätzliche mentale Schritt bedeutete, dass ich mich davor scheute, diese Bewegungen anzuwenden. Danke!
Sukima,

1
Das klingt nach etwas, das man mit InsertEnter / InsertLeave automatisch ausführen kann, um die relative Zeilennummerierung umzuschalten. Vermisse ich etwas?
Ben

Ich bin SEHR spät zur Party, aber @Ben hat recht, das sind nur ein paar Autocommand-Zeilen. Zum Beispiel in meinem vimrc habe ich set number, set relativenumberdann autocmd InsertEnter * :set norelativenumberundautocmd InsertLeave * :set relativenumber
B - Schicht

4

Ein weiterer Ansatz ist, dass Sie einfach eingeben können, wenn Sie versuchen, ein bestimmtes Muster zu löschen d/delimEnter.


2

Sie können den normalen Vorgang der Eingabe dplus einer Bewegung verwenden (wie bereits in den anderen Antworten erläutert). Das EasyMotion-Plugin bietet neue Bewegungen, mit denen Sie Ihr Problem schnell und einfach lösen können.

Angenommen, Sie möchten von der aktuellen Cursorposition bis zum Ende eines bestimmten Worts auf dem Bildschirm löschen, dann lauten die Bewegungstasten <Leader><Leader>e(ähnlich der normalen eBewegung). Geben Sie dann die hervorgehobenen Buchstaben ein, die am Ende des betreffenden Wortes erscheinen. Es gibt auch eine Linienbewegung, mit der Sie die aktuelle Linie bis zur betreffenden Linie löschen können <Leader><Leader>j.

Ich habe meinen <Leader>Schlüssel auf eingestellt ,. Der vollständige Befehl lautet also d<Leader><Leader>e{markierte (r) Buchstabe (n)}.

Von :help easymotion:

EasyMotion bietet eine viel einfachere Möglichkeit, einige Bewegungen in vim zu verwenden. Es nimmt den <number>aus <number>w oder <number>f {char}durch alle möglichen Wahlen hervorheben und so dass Sie eine Taste drücken , um direkt zum Ziel zu springen.

Wenn eine der verfügbaren Bewegungen ausgelöst wird, wird der gesamte sichtbare Text vor oder nach dem Cursor ausgeblendet und Bewegungsziele werden hervorgehoben.

Bearbeiten:

Das Github-Repository von EasyMotion finden Sie unter https://github.com/Lokaltog/vim-easymotion .

Dieser Reddit über Leute, die easymotion benutzen, könnte eine unterhaltsame Lektüre sein.


1

Es gibt eine einfache Lösung, die Ihr Problem lösen kann.

Stellen Sie den Cursor an den Anfang des Textblocks, den Sie entfernen möchten, und klicken Sie auf OK d50gg.

Dadurch werden alle Zeilen von Ihrer aktuellen Position bis zur 50. Textzeile gelöscht.

eq: Wenn sich Ihr Cursor in Zeile 46 befindet , d50ggwerden 4 Zeilen gelöscht .


1
Ich würde vorschlagen, Ganstelle von gg zu verwenden, da dies auch in vi funktioniert. Dies ist natürlich :set numberimmer hilfreich, um herauszufinden, zu welcher Zeilennummer die Zeile gehört, zu der Sie wechseln möchten.
Random832

Der springende Punkt dieser Frage ist, dass Sie nicht wissen, wie viele Zeilen Sie entfernen möchten.
200_erfolg

200_erfolg, Sie müssen nicht wissen, wie viele Zeilen Sie mit der Antwort, die ich gepostet habe, entfernen möchten. Alles, was Sie wissen müssen, ist "In welche Zeile möchten Sie entfernen"
Geee

1

Verwenden Sie den visuellen Modus mit Linienmarkierung.

  1. Setzen Sie den Cursor auf die oberste Zeile des zu entfernenden Text- / Codeblocks
  2. Drücken Sie Shift+v
  3. Bewegen Sie den Cursor an den unteren Rand des zu entfernenden Text- / Codeblocks
  4. Drücken Sie d

Ich bevorzuge diese Methode zum Löschen von Codeblöcken, da sie ganze Zeilen löscht, verglichen mit der einfachen Verwendung des visuellen Modus, bei dem Sie den Cursor in der rechten Spalte positionieren müssen, um das zu löschen, was Sie möchten.


3
Sie wiederholen die Antwort im Wesentlichen mit @ 200_success.
Martin Schröder

1

Ich mag es nicht, die relativenumberganze Zeit zu haben, deshalb habe ich mein Vim so konfiguriert, dass es nur aktiviert wird, wenn ich mich im visuellen Modus befinde:

" Entering Visual mode
nnoremap <silent>     v :set relativenumber cursorcolumn<CR>v
nnoremap <silent> <C-q> :set relativenumber cursorcolumn<CR><C-q>
nnoremap <silent>    gv :set relativenumber cursorcolumn<CR>gv
nnoremap <silent>     V :set relativenumber<CR>V

" When finished
augroup ClearCursorColumnAndLine
    autocmd!
    autocmd CursorHold * set norelativenumber nocursorcolumn nocursorline
augroup END

Das macht Ihre Aufgabe einfach:

V49jd

Denn nach einem Treffer können VSie sehen, wie weit die Ziellinie entfernt ist.

Dies mag sich auf lange Sicht als ärgerlich erweisen (der Text verschiebt sich nach rechts und links, wenn die relative Nummer aktiviert / deaktiviert ist), aber bisher gefällt es mir sehr gut.


1
Ich denke du benutzt v<Esc>d50j?
Martin Tournoij

Danke, ich hatte es ja falsch geschrieben. Eigentlich fange ich damit an, Vwenn ich weiß, dass ich eine zeilenweise Operation machen werde, und dann kann ich die dbis zuletzt verlassen, um mehr Vertrauen zu gewinnen.
Joeytwiddle

Meine Antwort scheint die Annäherung eines armen Mannes an die Zahlen zu sein . ;-)
joeytwiddle

1

Was für mich gut funktioniert hat vi:

  1. :set number um die Nummer der Zeile anzuzeigen, bis zu der ich löschen wollte;

    +1289 idle 
    +1289 idle 
    +1290 # <- I want to delete until here
    +1291 if [[ ! -z "$SFIN" ]]
    
  2. Gehen Sie zurück zu der Zeile, in der der Löschvorgang beginnen musste

  3. Löschung aus der aktuellen Zeile im normalen Modus> d1290G
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.