Vim sucht und ersetzt ausgewählten Text

109

Angenommen, wir haben einen Text, und ich gehe in den visuellen Modus und wähle Text aus. Wie kann ich schnell nach dem markierten Text suchen und ihn durch etwas anderes ersetzen?

Gabriel Solomon
quelle

Antworten:

135

Versuchen Sie Folgendes auszuführen oder geben Sie es in Ihre ein .vimrc

vnoremap <C-r> "hy:%s/<C-r>h//gc<left><left><left>

Durch Drücken von ctrl+ rim visuellen Modus werden Sie aufgefordert, Text einzugeben, durch den ersetzt werden soll. Drücken Sie enterund bestätigen Sie jede Änderung, mit der Sie einverstanden sind yoder die Sie ablehnen n.

Dieser Befehl überschreibt Ihr Register, hsodass Sie ein anderes auswählen können (indem Sie hden obigen Befehl in einen anderen Kleinbuchstaben ändern ), das Sie nicht verwenden.

Mykola Golubyev
quelle
13
Wenn Sie das weglassen cin gcErsetzen wird auf getan einmal im gesamten Puffer. Wenn Sie einen Fehler gemacht haben und ihn zurücksetzen möchten, geben Sie einfach den uBefehlsmodus ein. Ich mag diesen Ansatz besser, als jeden der Ersetzungen zu bestätigen (das passiert mit dem cModifikator).
Niloct
3
vmap * y:let @/ = @"<CR>ausgewählt ist hervorgehoben.
Kev
8
Was ist das Ziel von <left><left><left>?
Aymericbeaumet
7
@aymericbeaumet, um den Cursor zwischen die beiden Schrägstriche zu setzen. Auf diese Weise kann das Ersetzungswort einfach eingegeben werden.
Mcabrams
5
Beachten Sie, dass Sie, wenn Sie den Vorschlag von @ Niloct zum Entfernen des cvon befolgen gc, auch eines der <left>am Ende der Zeile entfernen müssen .
Nathan Friend
36

Diese schnelle und einfache Mapping-Suche nach visuell hervorgehobenem Text (ohne das h-Register zu überschreiben) und ohne Verwendung des terminalabhängigen + Registers:

" search for visually hightlighted text
vnoremap <c-f> y<ESC>/<c-r>"<CR>   

Wenn Ihnen die Strg-F nicht gefällt, ändern Sie sie nach Ihren Wünschen

Sobald der Text markiert ist, können Sie jederzeit eine sSubstitution durchführen, indem Sie einfach Folgendes eingeben:

%s//<your-replacement-string>

... weil eine leere Suche im sBefehl die zuletzt gesuchte Zeichenfolge verwendet.

ErichBSchulz
quelle
Wenn ich dies in meiner vim-Konfiguration verwende, control+fwählt ich immer das nächste Zeichen sowie das aus, was ich visuell ausgewählt habe. Irgendwelche Ideen?
Robert Mark Bram
%s//<your-replacement-string>scheint nicht zu funktionieren, um so etwas hervorzuheben /tmp/file. es wird nur<your-replacement-string>/tmp/file
naisanza
28

Dieser funktioniert auch (zumindest für Auswahlen in einer einzelnen Zeile / Auswahlen, die keine Sonderzeichen enthalten)

  • Wählen Sie den Text im visuellen Modus
  • ziehe den Text mit y
  • :s/<C-r>0/

0 ist das Ruckregister.

Wie andere bereits erwähnt haben, gibt es schnellere Möglichkeiten, dies zu tun. Wenn Sie jedoch gerade erst mit dem Erlernen von Vim begonnen haben (wie ich), ist dies eine der „allgemeinen“ Möglichkeiten.

// edit: Ich habe gerade festgestellt, dass der 'Register'-Ansatz fehlschlägt, wenn /die Auswahl Zeichen wie Tabulatoren oder Zeilenumbrüche oder Zeichen enthält (ich müsste diese Zeichen irgendwie manuell verarbeiten, damit der :sBefehl funktioniert):

Geben Sie hier die Bildbeschreibung ein

colemik
quelle
2
Es ist sehr einfach. Oh Gott, warum wird es nicht im Wiki behandelt. Komm schon ... Danke für die Antwort!
Benyamin Limanto
2
Dies ist die ideale Antwort für diejenigen von uns, die sich noch im frühen Teil der Vim-Lernkurve befinden. Ich weiß, dass Anpassung eine Stärke ist, aber ich möchte kein komplexes Skript kopieren und in mein vimrc einfügen und herausfinden, wie es für ein so einfaches Problem zusammenpasst. Diese Antwort hat mich gelehrt, dass Strg-R ein Register ausgibt, was in anderen Kontexten praktisch ist.
Nivek
26

Die akzeptierte Antwort funktioniert hervorragend, es sei denn, Ihre visuelle Auswahl enthält Sonderzeichen. Ich habe zwei Skripte (die hier veröffentlichten von Jeremy Cantrell und die von Peter Odding ) zusammen gehackt , um einen Befehl zu erstellen , mit dem Sie eine Zeichenfolge visuell auswählen können, die Sie suchen möchten, auch wenn sie spezielle Regex-Zeichen enthält.

" Escape special characters in a string for exact matching.
" This is useful to copying strings from the file to the search tool
" Based on this - http://peterodding.com/code/vim/profile/autoload/xolox/escape.vim
function! EscapeString (string)
  let string=a:string
  " Escape regex characters
  let string = escape(string, '^$.*\/~[]')
  " Escape the line endings
  let string = substitute(string, '\n', '\\n', 'g')
  return string
endfunction

" Get the current visual block for search and replaces
" This function passed the visual block through a string escape function
" Based on this - /programming/676600/vim-replace-selected-text/677918#677918
function! GetVisual() range
  " Save the current register and clipboard
  let reg_save = getreg('"')
  let regtype_save = getregtype('"')
  let cb_save = &clipboard
  set clipboard&

  " Put the current visual selection in the " register
  normal! ""gvy
  let selection = getreg('"')

  " Put the saved registers and clipboards back
  call setreg('"', reg_save, regtype_save)
  let &clipboard = cb_save

  "Escape any special characters in the selection
  let escaped_selection = EscapeString(selection)

  return escaped_selection
endfunction

" Start the find and replace command across the entire file
vmap <leader>z <Esc>:%s/<c-r>=GetVisual()<cr>/

Ich habe dies in mein vimrc aufgenommen, wenn das für irgendjemanden nützlicher ist.

bryan kennedy
quelle
2
Vielen Dank für die Lösung, mehrere Vorschläge kombiniert, endete ich mit den folgenden: vmap <C-r> <Esc>:%s/<c-r>=GetVisual()<cr>//g<left><left>(die nur alle in der Datei ersetzt)
Peter Butkovic
13

Ab Vim 7.4 können Sie die gnBewegung verwenden, mit der Textbereiche ausgewählt werden, die dem aktuellen Suchmuster entsprechen.

Nachdem Sie cgnden Text in der aktuell ausgewählten Übereinstimmung geändert (oder dgngelöscht) haben, können Sie im normalen Modus .den Befehl wiederholen und die nächste Übereinstimmung bearbeiten.

Es gibt eine Episode von Vimcast, die diese Funktion zeigt.

Dapeng Li
quelle
3
Das ist eine großartige Antwort!
Mauriciojost
Das ist auch super. abgesehen von colemik antwort. Tolle Sache!
Benyamin Limanto
Wow, es ist wie eines dieser Geheimnisse, die Sie finden, wenn Sie tief nach einer guten Lösung suchen, danke!
vdegenne
8

Mykola Golubyev, Danke für den Tipp! Im Folgenden wird das Register "+" verwendet, das (abhängig von Ihrem Terminal) bereits den hervorgehobenen Text enthält, wodurch die Verwendung des Registers "h" vermieden wird.

vnoremap <C-r> <Esc>:%s/<C-r>+//gc<left><left><left>
dmd
quelle
Mein VIM 7.0 unter CentOS 5.x scheint nicht das + -Register zu haben. Ist das eine Standardfunktion?
Dotancohen
3
Ich stelle fest, dass ich über Putty auf die CentOS-Maschine zugreife und beim Googeln sehe ich, dass + das Register der Zwischenablage ist. Putty scheint das nicht zu unterstützen! Diese Antwort ist also tatsächlich terminalabhängig.
Dotancohen
Hallo, ich habe Ihren Befehl ausprobiert, aber er fordert mich auf, das Vorkommen des angegebenen Textes in der gesamten Datei und nicht nur im ausgewählten Text zu ersetzen
solalito
7

Von http://vim.wikia.com/wiki/Search_and_replace_in_a_visual_selection :

Wenn Text visuell ausgewählt ist, drücken Sie:, um einen Befehl einzugeben. Die Befehlszeile gibt automatisch den Bereich ein:

:'<,'>

Sie können einen Befehl wie s / red / green / g eingeben, um jedes Rot in allen Zeilen der letzten visuellen Auswahl durch Grün zu ersetzen. Der Befehl wird wie folgt angezeigt:

:'<,'>s/red/green/g

Verwenden Sie den: history, um einen Ex-Befehl über einen zuvor ausgewählten Block zu wiederholen. Drücken Sie dann: und bearbeiten Sie einen vorherigen Befehl.

syvex
quelle
4
Ja, dies ersetzt Rot durch Grün im ausgewählten Bereich - sehr nützlich, aber nicht das, wonach die Operation gefragt hat.
ErichBSchulz
@ErichBSchulz Es macht es tatsächlich auf allen ausgewählten Zeilen. Selbst wenn nur ein Teil einer Linie ausgewählt ist, wird dies für die gesamte Linie ausgeführt.
Cully
1
Vielleicht beantwortet es die OP-Frage nicht, aber dies beantwortet genau meine Suche "vim suchen und durch visuelle Auswahl ersetzen", bei der ich die Suche und das Ersetzen nur auf die visuelle Auswahl beschränken möchte, die diese Frage
aufwirft
5

Ich habe dies in meinem vimrc:

function! GetVisual() range
    let reg_save = getreg('"')
    let regtype_save = getregtype('"')
    let cb_save = &clipboard
    set clipboard&
    normal! ""gvy
    let selection = getreg('"')
    call setreg('"', reg_save, regtype_save)
    let &clipboard = cb_save
    return selection
endfunction

vmap <leader>z :%s/<c-r>=GetVisual()<cr>/

Dadurch wird die visuelle Auswahl erfasst und ein Ersetzungsbefehl damit gestartet.

EDIT: Ich sollte darauf hinweisen, dass dies bei mehrzeiligen visuellen Auswahlen nicht funktioniert. GetVisual () hat zwar kein Problem damit, es zurückzugeben, aber ich bin mir nicht sicher, wie ich es richtig in die Befehlszeile einfügen soll. Wenn jemand Tipps dazu hat, kommentieren Sie dies bitte.

Jeremy Cantrell
quelle
2

Ich glaube nicht, dass Sie dies sofort tun können. Aber viele Leute mögen diese Funktion, also gibt es jede Menge Makros und dergleichen (ich habe sie selbst hinzugefügt). Hier ist eine, die Sie zum Beispiel hinzufügen können; Drücken Sie einfach *, um nach der nächsten Übereinstimmung für den visuell ausgewählten Text zu suchen.

John Feminella
quelle
2

Andere Antworten sind gut, aber sie entgehen keinen Sonderzeichen. Die Antwort von @brian kennedy zeigt eine Fluchtmethode, die jedoch viel Code erfordert. Im Fall einer URL ist beispielsweise ein Escapezeichen obligatorisch, oder die Suche wird mit ":" beendet.

Wie in vim.fandom.com/wiki/Search_for_visually_selected_text geschrieben , können Sie einen Oneliner erstellen, um einige Zeichen zu suchen und zu maskieren. Du kannst den Charakteren entkommen, die du willst. Ich habe mich entschieden zu entkommen /\: :

vnoremap // y/\V<C-R>=escape(@",'/\:')<CR><CR>

Bei dieser Karte muss ich //im visuellen Modus drücken , um den aktuell ausgewählten Text im gesamten Puffer zu durchsuchen.

RomainTT
quelle
1

Meine Lieblingskurzversion davon ist

vnoremap s / y: s / "/

Dann können Sie eine Auswahl markieren und einfach s / drücken, um einen Ersetzungsbefehl dafür zu starten.

Alex
quelle
Hat bei mir nicht funktioniert, "buchstäblich behandelt . <c-r>"arbeitete aber
Josh Bodah
1

Ich habe nicht den Repräsentanten, um einen Kommentar abzugeben, also füge ich noch eine weitere Antwort hinzu ...

vnoremap <C-r> "0y<Esc>:%s/<C-r>0//g<left><left>

@dmd und @dotancohen: Dies funktionierte bei mir ohne zu verbrauchen "h(verwendet explizit 0, was ohnehin die letzte Position ist) und funktioniert mit Kitt ssh -> mint (lmde); Ich weiß nichts über Cent. Verwendet auch Kommentare von @Niloct und @Nathan Friend, um die Bestätigung zu entfernen.

10'004
quelle
1

Beispiel 1. Zitieren Sie die Auswahl mit Sternen und halten Sie den Cursor am Anfang der Auswahl.

:%s,\%#\%V\_.*\%V/,**&**,c 

Beispiel 2. Pipe ausgewählten Text mit base64:

:%s!\%#\%V\_.*\%V!\=system("base64 -w 0",@")!c

Erklärung LHS:

\%# matches cursor 
\%V matches inside the selection only
\_. matches any character.
\_.* matches beginning to end of selection.

Erklärung RHS:

\=expr()  Replace match with result of expr() for each substitution.
mosh
quelle
0

Ich hatte gehofft, dass es in Vim einen eingebauten Weg gibt, um ein Wort zu ersetzen, ohne das Wort überhaupt neu eingeben zu müssen. Es gibt, obwohl es nur für Text bis zu einem Wortbegrenzungszeichen funktioniert.

Wenn Sie mit der Maus über das Wort gefahren sind, drücken Sie *oder #, um das Wort hervorzuheben, und springen Sie zum nächsten / vorherigen Speicherort (wenn Sie den Speicherort in der Datei nicht ändern möchten, drücken Sie die entgegengesetzte Taste, um zum Speicherort zurückzukehren du warst gerade bei).

Dann geben Sie einfach ein:

%s//<your-replacement-string>

Wie in der Antwort %seiner anderen Person erwähnt, wird bei Verwendung eines leeren Eintrags zwischen den Schrägstrichen das zuvor gesuchte Wort verwendet. Durch Drücken von *oder #suchen Sie unter dem Cursor nach dem Wort, wodurch es zum zuletzt gesuchten Wort wird.

Am Ende sind es nur sechs oder sieben Tastenanschläge + Länge des Ersatzworts, um dies auszuführen, und es erfordert kein Makro oder eine Bearbeitung Ihres .vimrc.

Cameron Gagnon
quelle