Ähnlich wie bei der Antwort unter /vi//a/818/227 können Sie den globalen Befehl verwenden.
Damit können Sie vim anweisen, nach Linien zu suchen, die einem Muster entsprechen, und dann Befehle ausführen.
In Ihrem Fall möchten Sie Zeilen, die mit "Level N:" beginnen, Text voranstellen, damit unser globaler Befehl lautet
:g/^Level \d:/{COMMANDS}
Verwenden des Ersatzbefehls (Ersetzen regulärer Ausdrücke) für den Befehl
Die Befehle machen mehr Spaß. Normalerweise ersetze ich gerne reguläre Ausdrücke für solche Dinge, da es einfach ist, Variablen zu verwenden.
Beispiel für Ihre Frage
:let i = 1 | g/^Level \d:/s/^/\=printf("%02d ", i)/ | let i = i+1
Wie es funktioniert
Im Ersetzungsabschnitt eines Substitutionsbefehls kann ein Ausdruck stehen.
Als erstes setzen wir eine Variable i
als Startnummer. Ich habe 1 gewählt, aber jede Zahl reicht aus.let i = 1
Dann führen wir unseren globalen Befehl aus, der uns dazu veranlasst, eine Aktion für übereinstimmende Zeilen auszuführen. g/^Level \d:/
Wir lassen unseren globalen Befehl den Wert einfügen und unseren Zähler mit dem Substitutionsbefehl und dem Befehl let erhöhen. s/^/\=printf("%02d ", i)/ | let i = i+1
Der reguläre Ausdruck des Substitutionsbefehls findet den Zeilenanfang ^
und ersetzt ihn durch einen Ausdruck. Unser Ausdruck ist das Ergebnis eines formatierten Drucks. Wie in der C-Sprache verwendet vims printf Formatierungsparameter. %02d
bedeutet, ein Argument so zu konvertieren, als wäre es eine Dezimalzahl d
, die mindestens 2 Leerzeichen belegt 2
und mit 0 auffüllt 0
. Einzelheiten und andere Konvertierungsoptionen (einschließlich Gleitkommaformatierung) finden Sie unter :help printf
. Wir geben printf unsere Zählvariable i
und es gibt uns 01
das erste Mal, 02
das zweite Mal usw. Dies wird vom Substitutionsbefehl verwendet, um den Zeilenanfang zu ersetzen und das Ergebnis des printf am Anfang effektiv einzufügen.
Beachten Sie, dass ich nach dem d ein Leerzeichen setze : "%02d "
. Sie haben in der Frage nicht danach gefragt (und ich habe keine Beispielausgabe gesehen), aber ich vermutete, dass Sie die Nummer vom Wort "Level" trennen wollten. Entfernen Sie das Leerzeichen aus der Zeichenfolge, die printf zugewiesen wurde, damit die eingefügte Nummer direkt neben dem L in Level angezeigt wird.
Schließlich let i = i + 1
erhöht dies unseren Zähler nach jeder Ersetzung.
Dies kann allgemein angewendet werden, um Teile von Linien, die mit anderen Kriterien übereinstimmen, durch beliebige Funktionsdaten zu ersetzen.
Kombinierte normale Befehle verwenden
Dies ist gut für einfache Einfügungen oder komplexe Bearbeitungen. Wie beim Ersetzen verwenden wir global, um eine Übereinstimmung zu erzielen, aber anstelle der Ersetzung durch reguläre Ausdrücke führen wir eine Reihe von Operationen aus, als ob sie vom Benutzer eingegeben würden.
Beispiel für Ihre Frage
:let i = 1 | g/^Level \d:/execute "normal! I" . printf("%02d ", i) | let i = i+1
Wie es funktioniert
Die verwendeten Werte sind dem Ersatz sehr ähnlich (wir verwenden immer noch printf, um unsere Zahl so zu formatieren, dass sie mit 2 Ziffern auf 0 aufgefüllt wird), aber die Operation ist anders.
Hier verwenden wir den Befehl execute, der eine Zeichenfolge verwendet und die Zeichenfolge als ex-Befehl ausführt ( :help :exe
). Wir konstruieren einen String, der "normal! I" mit unseren Daten kombiniert, der beim ersten Mal "normal! I01" und beim zweiten Mal "normal! I02" usw. ist.
Der normal
Befehl führt Operationen wie im normalen Modus aus. In diesem Beispiel lautet unser normaler Befehl I
am Anfang der Zeile. Wenn wir es verwendet dd
hätten, o
würde es die Zeile löschen, würde eine neue Zeile nach der übereinstimmenden Zeile öffnen. Es ist, als hätten Sie selbst I
(oder andere Vorgänge) im normalen Modus getippt . Wir verwenden das !
After normal
, um sicherzustellen, dass keine Zuordnungen im Weg sind. Siehe :help :normal
.
Was dann eingefügt wird, ist der Wert unseres printf, wie im ersten Beispiel für die Verwendung von Ersatz.
Diese Methode kann ausgefallener sein als Regex, da Sie Dinge wie tun können execute "normal! ^2wy" . i . "th$p"
, die an den Anfang des Textes gehen ^
, 2 Wörter vorwärts bewegen 2w
, bis zum i-ten 'h'-Zeichen y" . i . "th
ziehen, bis zum Ende der Zeile gehen $
und einfügen p
.
Dies ist fast so, als würde man ein Makro ausführen, verbraucht jedoch kein Register und kann Zeichenfolgen aus beliebigen Ausdrücken kombinieren. Ich finde das sehr mächtig.
Nähere dich, wo jedes Level seinen eigenen Zähler hat
Vielleicht möchten Sie, dass jedes Level seinen eigenen Zähler erhält. Wenn Sie die maximale Anzahl von Ebenen im Voraus kennen, können Sie Folgendes tun (das Hinzufügen von zusätzlichem Code, um die größte Ebene zu finden, ist möglicherweise nicht allzu schwierig, würde diese Antwort jedoch zu lang machen. Dies wird immer länger).
Lassen Sie zunächst i frei, falls wir es bereits als Ganzzahl verwendet haben. Wir können i nicht in eine Liste konvertieren, wir müssen es so erstellen.
:unlet! i
Als nächstes setzen wir i als eine Liste, die die Anzahl der Ebenen enthält. Sie haben 2 in Ihrer Frage gezeigt, aber nehmen wir zum Spaß 10 an. Da die Listenindizierung auf 0 basiert und ich mich nicht darum kümmern möchte, 1 basierend auf Ihrer Liste zu korrigieren, erstellen wir einfach genug Elemente (11) und verwenden niemals den 0-Index.
:let j = 0
:let i = []
:while j < 11 | let i += [1] | let j += 1 | endwhile
Als nächstes brauchen wir einen Weg, um die Levelnummer zu erhalten. Glücklicherweise ist Ersatz auch als Funktion verfügbar, daher geben wir ihm unsere Zeile und extrahieren die Ebenennummersubstitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")
Da i jetzt eine Liste von 11 1
s ist (jeder Index ist der Zähler für unser Niveau), können wir jetzt eines der obigen Beispiele anpassen, um das Ergebnis dieser Substitution zu verwenden:
Über Ersatzbefehl:
:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | s/^/\=printf("%02d ", i[ind])/ | let i[ind] += 1
Über normalen Befehl:
:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | execute "normal! I" . printf("%02d ", i[ind]) | let i[ind] += 1
Beispieleingabe:
Level 1: stuff
Level 1: Stuff
Some text
Level 3: Other
Level 1: Meh
Level 2: More
Beispielausgabe:
01 Level 1: stuff
02 Level 1: Stuff
Some text
01 Level 3: Other
03 Level 1: Meh
01 Level 2: More