Wenn ich mit suche
/\vSEARCHTERM
Vim startet die Suche von der Cursorposition nach unten und wird nach oben gewickelt. Allerdings beim Suchen und Ersetzen mit
:%s/\vBEFORE/AFTER/gc
Vim beginnt oben in der Datei.
Gibt es eine Möglichkeit Vim zu machen perform Suchen und Ersetzen von der Cursorposition und nach oben Umwickeln einmal das Ende erreicht?
\vpattern
- 'sehr magisches' Muster: Nicht-alphanumerische Zeichen werden als spezielle Regex-Symbole interpretiert (kein Entkommen erforderlich)%
? Ich sehe keinen vernünftigen Nutzen dafür, dass Sie sowieso die ganze Datei durchgehen.Antworten:
1. Es ist nicht schwer, das Verhalten durch eine zweistufige Substitution zu erreichen:
Zunächst wird für jede Zeile ein Ersetzungsbefehl ausgeführt, der von der aktuellen bis zum Ende der Datei beginnt. Dann wird dieser
:substitute
Befehl mit demselben Suchmuster, derselben Ersatzzeichenfolge und denselben Flags mit dem:&
Befehl wiederholt (siehe:help :&
).Letzterer führt jedoch die Ersetzung für den Zeilenbereich von der ersten Zeile der Datei bis zur Zeile durch, in der die vorherige Kontextmarke gesetzt wurde, minus eins. Da der erste
:substitute
Befehl die Cursorposition speichert, bevor mit dem eigentlichen Ersetzen begonnen wird, ist die von adressierte''
Zeile die Zeile, die die aktuelle war, bevor dieser Ersetzungsbefehl ausgeführt wurde. (Die''
Adresse bezieht sich auf die'
Pseudomarke; siehe:help :range
und:help ''
für Details.)Beachten Sie, dass der zweite Befehl (nach dem
|
Befehlstrennzeichen - siehe:help :bar
) keine Änderung erfordert, wenn das Muster oder die Flags im ersten geändert werden.2. Um einige Eingaben zu sparen und das Grundgerüst des obigen Substitutionsbefehls in der Befehlszeile aufzurufen, können Sie eine Zuordnung im Normalmodus wie folgt definieren:
Der nachfolgende
<c-b><right><right><right><right>
Teil ist erforderlich, um den Cursor zwischen die ersten beiden Schrägstriche zu setzen, damit der Benutzer mit der Eingabe des Suchmusters beginnen kann. Sobald das gewünschte Muster und Ersetzen fertig sind, kann der resultierende Befehl durch Drücken von ausgeführt werden Enter.( Wenn Sie das Muster lieber eingeben möchten, sollten Sie
//
anstelle des///
obigen Mappings den Trennstrich selbst eingeben, gefolgt von der Ersatzzeichenfolge, anstatt den Cursor mit dem Rechtspfeil über den bereits vorhandenen Trennstrich zu bewegen das Ersatzteil.)quelle
:noremap <leader>R :,$s///gc\|1,''-&&<c-b><right><right><right><right>
. Es:,$s///gc|1,''-&&
wird mit dem Cursor zwischen den ersten beiden Schrägstrichen in die Befehlszeile eingefügt. Sobald Sie das gewünschte Muster eingegeben und ersetzt haben, können Sie den resultierenden Befehl ausführen, indem Sie die Eingabetaste drücken .Sie verwenden bereits einen Bereich,
%
der kurz für die1,$
Bedeutung der gesamten Datei steht. Um von der aktuellen Zeile zum Ende zu gelangen, verwenden Sie.,$
. Der Punkt bedeutet aktuelle Zeile und$
bedeutet die letzte Zeile. Der Befehl wäre also:Es
.
kann jedoch davon ausgegangen werden, dass die oder die aktuelle Zeile entfernt werden kann:Weitere Hilfe finden Sie unter
quelle
10:s/pattern/replace/gc
%
ist eine Verknüpfung für1,$
(Vim help =>
:help :%
gleich 1, $ (die gesamte Datei).).
ist die Cursorposition, damit Sie dies tun könnenVom Anfang des Dokuments bis zum Cursor ersetzen
etc
Ich empfehle dringend, dass Sie das Handbuch über den Bereich lesen,
:help range
da so gut wie alle Befehle mit einem Bereich arbeiten.quelle
Ich habe ENDLICH eine Lösung für die Tatsache gefunden, dass das Beenden der Suche bis zum Anfang der Datei reicht, ohne eine enorme Funktion zu schreiben ...
Sie würden nicht glauben, wie lange ich dafür gebraucht habe. Fügen Sie einfach eine Eingabeaufforderung zum Umbrechen hinzu: Wenn der Benutzer
q
erneut drückt , wird nicht umbrochen. Also im Grunde, beenden Suche durch Tippenqq
stattq
! (Und wenn Sie einpacken möchten, geben Sie einfach einy
.)Ich habe dies tatsächlich einem Hotkey zugeordnet. Wenn Sie beispielsweise jedes Wort unter dem Cursor ab der aktuellen Position suchen und ersetzen möchten, durch
q*
:quelle
q
,l
oder Esc ) und wollen nicht von oben fortzusetzen, können Sie bereits drückenq
oder Esc erneut den zweiten Befehl sofort zu beenden. Das heißt, das vorgeschlagene Hinzufügen der Eingabeaufforderung scheint die bereits vorhandene Funktionalität effektiv zu duplizieren.yyyq
, die Bearbeitung ohne verwirrende Sprünge fortzusetzen. Aber esyyyqq
ist fast genauso gut, wenn man ein doppeltes Tippen in Bezug auf die Benutzerfreundlichkeit als ein einfaches Tippen betrachtet.q
zweiten Drückens war). Letzterer verlässt den Cursor beim letzten Auftreten, das ersetzt wurde (kurz bevor das ersteq
gedrückt wurde).norm!``
Befehl einfach angehängt werden ::,$s/BEFORE/AFTER/gc|1,''-&&|norm!``
.Hier ist etwas sehr Grobes, das die Bedenken bezüglich des Umlaufens der Suche mit dem zweistufigen Ansatz (
:,$s/BEFORE/AFTER/gc|1,''-&&
) oder mit einem Zwischenprodukt "Weiter am Anfang der Datei?" Ansatz:Diese Funktion verwendet einige Hacks, um zu überprüfen, ob wir uns nach oben wickeln sollen:
quelle
Ich bin zu spät zur Party, aber ich habe mich zu oft auf solche späten Stackoverflow-Antworten verlassen, um es nicht zu tun. Ich habe Hinweise zu reddit und stackoverflow gesammelt. Die beste Option ist, das
\%>...c
Muster in der Suche zu verwenden, das erst nach Ihrem Cursor übereinstimmt.Das heißt, es bringt auch das Muster für den nächsten Austauschschritt durcheinander und ist schwer zu tippen. Um diesen Effekten entgegenzuwirken, muss eine benutzerdefinierte Funktion das Suchmuster anschließend filtern und somit zurücksetzen. Siehe unten.
Ich habe mich mit einem Mapping auseinandergesetzt, das das nächste Vorkommen ersetzt und zu dem folgenden springt, und nicht mehr (war sowieso mein Ziel). Ich bin sicher, darauf aufbauend kann eine globale Substitution ausgearbeitet werden. Denken Sie daran, wenn Sie an einer Lösung arbeiten, die darauf abzielt,
:%s/.../.../g
dass das folgende Muster Übereinstimmungen in allen Zeilen herausfiltert , die noch an der Cursorposition verbleiben. Sie werden jedoch nach Abschluss der einzelnen Ersetzung bereinigt, sodass dieser Effekt direkt nach dem Springen verloren geht nächstes Spiel und kann somit alle Spiele einzeln durchlaufen.fun! g:CleanColFromPattern(prevPattern) return substitute(a:prevPattern, '\V\^\\%>\[0-9]\+c', '', '') endf nmap <F3>n m`:s/\%><C-r>=col(".")-1<CR>c<C-.r>=g:CleanColFromPattern(getreg("/"))<CR>/~/&<CR>:call setreg("/", g:CleanColFromPattern(getreg("/")))<CR>``n
quelle