2016-10-13 2 views
1

In vim, in einem Windows-Rechner (ohne Zugriff auf "Unix" -ähnliche Befehle wie Befehlsspalte) möchte ich diesen Code neu formatieren, um es lesbarer zu machen:Ausrichten von Text nach n-ten Spalte in vim Entfernen unnötiger Leerzeichen

COLUMN KEY_ID  FORMAT 9999999999 
COLUMN VALUE_1       FORMAT 99 
COLUMN VALUE_2       FORMAT 99 
COLUMN VALUE_3    FORMAT 999 
COLUMN VALUE_4  FORMAT 999 

Und ich möchte dies als weniger Befehle wie möglich verwenden haben:

COLUMN KEY_ID  FORMAT 9999999999 
COLUMN VALUE_1  FORMAT 99 
COLUMN VALUE_2  FORMAT 99 
COLUMN VALUE_3  FORMAT 999 
COLUMN VALUE_4  FORMAT 999 

Hinweis dies nur ein Auszug ist, da es viele weitere Zeilen, in denen ich muss das gleiche tun.

+2

Installieren Sie die [tabellarische] (https://github.com/godlygeek/tabular) Plugin und Lauf ': Tabularize'. –

Antwort

4

Sie können den folgenden Befehl verwenden:

:%s/\w\zs\s*\zeFORMAT/^I 

Das Muster wird die Leerzeichen zwischen FORMAT und dem Ende des vorherigen Wortes und ersetzen sie durch eine Lasche entsprechen:

\w  Any 'word' character 
\zs  Start the matching 
\s*  Any number of whitespace 
\ze  End the matching 
FORMAT The actual word format 

\zs und \ze Erlaube, die Ersetzung nur auf die Leerzeichen anzuwenden, siehe: :h /\zs und :h /\ze

Beachten Sie, dass ^I sollte es eine gute Art und Weise zu tun, wäre mit Strg + vRegisterkarte

Die tabular plugin empfohlen von @SatoKatsura eingefügt werden.


Sie können das auch verallgemeinern. Angenommen, Sie haben die folgende Datei:

:%s/^\(\w*\s\)\{1}\w*\zs\s*\ze/ 

wurden die Muster so detailliert sein können:

^     Match the beginning of the line 
\(\w*\s\)\{1}  One occurrence of the pattern \w*\s i.e. one column 
\w*    Another column 
\zs\s*\ze   The whitespaces after the previous column 

Sie könnten den Wert ändern

COLUMN KEY_ID   FORMAT 9999999999 
COLUMN VALUE_1      FOO 99 
COLUMN VALUE_2  BAR 99 

Sie diesen Befehl verwenden könnte \{1}, um den Befehl für die nächsten Spalten anzuwenden.


EDIT @aturegano Kommentar zu antworten, hier ist ein Weg, um die Spalte zu einem anderen zu richten:

%s/^\(\w*\s\)\{1}\w*\zs\s*\ze/\=repeat(' ', 30-matchstrpos(getline('.'), submatch(0))[1]) 

Die Idee ist immer noch die Whitespaces entsprechen, die auf dem ausgerichtet werden müssen, zweiten Teil des Ersetzungsbefehls verwenden wir einen Sub-Replace-Ausdruck (siehe :h sub-replace-expression).

Dies ermöglicht es uns, einen Befehl aus dem Substitutionsteil zu verwenden, die wie folgt erklärt werden kann:

\=     Interpret the next characters as a command 
repeat(' ', XX) Replace the match with XX whitespaces 

XX is decomposed like this: 
30-     30 less the next expression 
matchstrpos()[1] Returns the columns where the second argument appears in the first one 
getline('.')  The current line (i.e. the one containing the match 
submatch(0)   The matched string 
[1]     Necessary since matchstrpos() returns a list: 
         [matchedString, StartPosition, EndPosition] 
        and we are looking for the second value. 

Sie dann einfach haben 30 durch die Spalte zu ersetzen, wo Sie Ihre nächste Spalte verschoben werden soll.

Siehe :h matchstrpos(), :h getline() und :h submatch()

+0

Sehr guter Ansatz und detaillierte Erklärung. Ich habe oben nicht erwähnt, dass ich keine Registerkarte im Code hinzufügen möchte. Der Ausdruck ':% s/^ \ (\ w * \ s \) \ {1} \ w * \ zs \ s * \ ze /' entspricht dem, was ich ändern möchte. Gibt es eine Möglichkeit, "fill with spaces" anzugeben bis Spalte n "? – aturegano

+0

@aturegano Ich denke, dass für solch einen Anwendungsfall das tabellarische Plugin der einfachste Weg wäre. Vielleicht können Sie etwas hacken dank dem Sub-Replace-Ausdruck ([': h sub-replace-expression'] (http://vimdoc.sourceforge.net/htmldoc/change.html#sub-replace-expression)): Du würdest den zweiten Teil '/^I 'durch'/\ = etwas ersetzen, wobei' etwas 'ein Test der Spalte und die Anzahl der zu addierenden Leerzeichen wäre, aber ich bin mir nicht sicher, ob das möglich ist. – statox

+0

@aturegano Ich habe eine Lösung gefunden, siehe meine Bearbeitung und sage mir, ob das gewünscht wird :-) – statox

2

eine Antwort Posting wie gewünscht:

:g/^COLUMN/s/.*/\=call('printf', ['%s %-30s %s %s'] + split(submatch(0)))/ 

Erläuterung:

  • g/^COLUMN / - wenden Sie den folgenden Befehl Linien passende /^COLUMN / (vgl :h :global)
  • \= - ersetzt werden, mit dem Ergebnis der Auswertung eines Ausdrucks, anstatt mit einer festen Zeichenkette (vgl :h s/\=)
  • submatch(0) - in Worte Spaltlinie
  • printf(...) - die Linie
  • split(...) abgestimmt ist - formatieren Sie die Linie
  • call(...) - wir möchten, dass printf('%s %-30s %s %s', list) haben, aber printf() braucht nicht „real“ Listen als Argumente, so müssen wir die Liste mit einem call(...) (vgl entfalten :h call()).
0

Noch eine andere Lösung:

:%s/ \{2,}/ /g 

Diese Lösung ist nicht perfekt, denn das Ergebnis wird ein zusätzliches Einzel Platz auf der ersten Zeile haben. So beheben Sie dieses Problem:

:%s/\%>15c \{2,}/ /g 

Erklärung der Muster:

%>15c\s\{2,} 

%>15c     Matches only after column 15 

    \s\{2,}   Matches two or more white spaces 
Verwandte Themen