Wie werden Tabulatoren durch Leerzeichen ersetzt?

85

Ist es möglich, Tabulatoren unter Beibehaltung der Textausrichtung in Leerzeichen umzuwandeln?

Einfach zu ersetzen funktioniert nur dann sinnvoll, wenn keine führenden Zeichen vorhanden sind.

ideasman42
quelle
Wenn Sie vim-faq installiert haben , können Sie dort eine Offline-Antwort erhalten: :h vim-faqund suchen /tab characters. Das schwer zu merkende Tag ist :h faq-14.16.
Hotschke

Antworten:

98

Sie können den :retabBefehl verwenden. Von :help :retab

Ersetzen Sie alle Sequenzen des Leerraums, die a enthalten, <Tab>durch neue Zeichenfolgen des Leerraums, indem Sie den neuen angegebenen Tabulatorwert verwenden. Wenn Sie keine neue Tabstop-Größe angeben oder diese Null ist, verwendet Vim den aktuellen Wert von 'tabstop'. [...] 'expandtab'Wenn diese Option aktiviert ist, ersetzt Vim alle Registerkarten durch die entsprechende Anzahl von Leerzeichen.

Beachten Sie, dass der Befehl einen Bereich akzeptiert, sodass Sie eine visuelle Auswahl treffen können und dann nur :retabdie ausgewählten Linien.

Guillem
quelle
Cool! Funktioniert schnell und einfach!
DenisKolodin
2
Wie wäre es mit einem Beispiel?
Petr
23

Sie können jedoch :retabwie angegeben alle Tabulatoren in Leerzeichen ändern und nicht nur die Tabulatoren am Zeilenanfang

Also das (wo ist ein Tabulatorzeichen):

if :; do
⇥echo "⇥hello"
end

wird geändert in (wo ist ein Leerzeichen):

if :; do
␣␣echo "␣␣hello"
end

Dies kann in einigen Szenarien zu unerwarteten Nebenwirkungen führen, und es ist noch problematischer, wenn Leerzeichen in Tabulatoren geändert werden!

Also schrieb ich eine kleine Funktion ändern nur tabs / Leerzeichen am Anfang der Zeile:

" :retab changes *everything*, not just start of lines
fun! Retab(expandtab)
    let l:spaces = repeat(' ', &tabstop)

    " Replace tabs with spaces
    if a:expandtab
        silent! execute '%substitute#^\%(' . l:spaces . '\)\+#\=repeat("\t", len(submatch(0)) / &tabstop)#e'
    " Replace spaces with tabs
    else
        silent! execute '%substitute#^\%(\t\)\+#\=repeat("' . l:spaces . '", len(submatch(0)))#e'
    endif
endfun

Bei dieser Version müssen Sie expandtabden Funktionsaufruf manuell angeben (dh :call Retab(1)Tabulatoren in Leerzeichen ändern), Sie können ihn jedoch auch so ändern, dass er den aktuellen Wert von &expandtab(wie bereits bei &tabstop) annimmt, wie dies der :retabFall ist. (Ich bevorzuge es, es manuell anzugeben).

Martin Tournoij
quelle
6
Es gibt auch eine Antwort zu SO, die nur das Retabbing am Zeilenanfang abdeckt. Wegen der Klarheit dieser Erklärung lohnt es sich, sie zu verlinken.
6.
Könnte jemand erklären , was Brief tut ain if a:expandtabbedeuten?
John cj
Auch scheinen die Verhältnisse umgekehrt zu sein (ein Witz: D?). Wenn Sie set expandtabin Ihrer .vimrc und dann haben autocmd BufWritePre * :call Retab(&expandtab)- Einrückung wird zu Tabulatoren anstelle von Leerzeichen geändert.
John cj
11

Vim stellt einen !retabBefehl zur Verfügung, der alle Sequenzen von <Tab>durch neue Leerzeichenfolgen ersetzt, wobei der neue Tabulatorwert (z. B. :set tabstop=2) verwendet wird. Alle Tabulatoren in Zeichenfolgen können jedoch geändert werden (z. B. in einem C-Programm sollten Sie \tdies vermeiden).

Alternativ können Sie alle Tabulatoren mit dem folgenden Befehl in Leerzeichen ändern:

:%s/\t/  /g

oder wie von @Shahbaz vorgeschlagen :

:%s/^\t\+/ g

Es werden also nur die im Einzug verwendeten Tabulatoren konvertiert.

Erläuterung:

  • %repräsentiert den gesamten Puffer / die gesamte Datei ( :help :%)
  • ssteht für substitute ( :help sub-replace-special)
  • \t, oder ^Isteht für tab
  • - Verwenden Sie so viele Leerzeichen, wie Sie für eine Registerkarte benötigen
  • g - steht für global und konvertiert mehrere Tabulatoren in derselben Zeile

Dann Vertiefung der gesamten Datei zu korrigieren, können Sie versuchen: gg=G. Überprüfen Sie: Weitere Informationen zum erneuten Einrücken von schlecht eingerücktem Code .

Um standardmäßig Leerzeichen anstelle von Tabulatoren zu verwenden, müssen Sie Ihrer .vimrcDatei die folgenden Einstellungen hinzufügen :

set tabstop=2     " (ts) width (in spaces) that a <tab> is displayed as
set expandtab     " (et) expand tabs to spaces (use :retab to redo entire file)
set shiftwidth=2  " (sw) width (in spaces) used in each step of autoindent (aswell as << and >>)

Alternative Lösung ist zu verwenden tidy


Verbunden:

Kenorb
quelle
1
Ich würde zumindest %s/^\t\+/ gso vorgehen, dass nur die Tabulatoren konvertiert werden, die beim Einrücken verwendet werden. Auch gg=Gkönnte mit Sprachen wie Python katastrophal sein.
Shahbaz
3

Versuchen Sie es mit:

expand -t 4 input_filename output_filename

expandist ein Befehlszeilenprogramm zum Konvertieren von Tabulatoren in Leerzeichen, die Sie aus einer Shell oder mit ausführen können :!expand.

Es ist in POSIX , sollte also auf den meisten Systemen verfügbar sein. unexpandwird übrigens das Gegenteil tun.

Ankit Shah
quelle
2
Was ist expand?
muru
Expand ist ein eingebauter Terminalbefehl zum Kopieren von Tabulatorzeichen in Leerzeichen. Eine detaillierte Beschreibung finden Sie unter folgendem Link. computerhope.com/unix/uexpand.htm
Ankit Shah
2
Wenn dies externe Befehle sind, sollten Sie dies erwähnen.
muru
Weitere Beschreibung hinzugefügt. Bitte überprüfen Sie
Ankit Shah
5
Sie könnten es auch einfach :%!expand -t 4innerhalb von vim tun . Besser noch, Sie könnten auch die aktuelle Option für die Verschiebebreite verwenden: :exe '%!expand -t ' . &shiftwidth
EvergreenTree
1

Der Vollständigkeit =halber können Sie auch Einrückungen korrigieren, nachdem Sie angegeben haben, dass Tabulatoren durch Leerzeichen ersetzt werden. Im normalen Modus können Sie dies durch Eingabe tun :set expandtab. Dann =könnte auf zwei Arten verwendet werden:

  • Im visuellen Modus =würde ein einzelnes Einrücken ausgewählter Codeblöcke korrigieren.
  • Im normalen Modus wird gg=Gdie gesamte Datei repariert, wobei ggder Cursor an den Anfang der Datei bewegt wird , dann =angewendet wird und Gder Cursor an das Ende der Datei bewegt wird.

Verweis: Link

Samuel Li
quelle
Dies setzt voraus, dass vim den aktuellen Einzug korrekt neu berechnen kann (möglicherweise nicht) - auch für unstrukturierte Dateien oder Code, der in einem anderen Editor mit geringfügig anderen Einzugsregeln geschrieben wurde.
ideasman42
Vielen Dank @ ideasman42; Ich habe der Antwort hinzugefügt, um vollständiger zu sein.
Samuel Li