Ich habe ein Problem, bei dem ich mir zwei allgemeine Lösungsansätze vorstellen kann, aber ich kenne keine Einzelheiten für beide Ansätze.
...
Level 1: cũng also
Level 1: và and
Level 1: như like; such as
Level 2: các plural marker
Level 2: của belonging to
...
Für jede Zeile, die mit "Level n" beginnt, möchte ich eine Zahl einfügen, die mit "01" beginnt. Der Einfachheit halber stellen wir die Zahl voran.
Ansatz 1: Wählen Sie alle Linien mit derselben Ebene manuell aus. Rufe Magie an, die ich bald lernen werde.
Ansatz 2: Schreiben Sie eine Suche und ersetzen Sie sie, wobei alle Zeilen mit der angegebenen Ebene übereinstimmen, die bei jeder Übereinstimmung eine Zahl im Ersetzungstext enthält, die bei jeder Übereinstimmung um eins erhöht wird.
Ich habe ähnliche Fragen auf StackOverflow oder auf anderen Vim-Sites gefunden, aber jede scheint eines oder mehrere der folgenden Probleme zu haben:
- Hier geht es darum, die aktuelle Zeilennummer anstelle einer beliebigen, aber inkrementellen Nummer einzufügen.
- Füllt die Nummer nicht auf Null.
- Funktioniert nicht für Auswahlen auf meinem Vim 7.4 unter Windows 7. (Diese führen zu dem Fehler
E481: No range allowed
.)
Ich verwende gVim in Windows mit mswin.vim, aber eine Lösung, die auf allen Vanilla Vim-Installationen funktioniert, ohne das Setup anpassen zu müssen, ist möglicherweise am besten.
Antworten:
Ä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
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
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 Dezimalzahld
, die mindestens 2 Leerzeichen belegt2
und mit 0 auffüllt0
. Einzelheiten und andere Konvertierungsoptionen (einschließlich Gleitkommaformatierung) finden Sie unter:help printf
. Wir geben printf unsere Zählvariablei
und es gibt uns01
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
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 BefehlI
am Anfang der Zeile. Wenn wir es verwendetdd
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 selbstI
(oder andere Vorgänge) im normalen Modus getippt . Wir verwenden das!
Afternormal
, 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 bewegen2w
, bis zum i-ten 'h'-Zeicheny" . i . "th
ziehen, bis zum Ende der Zeile gehen$
und einfügenp
.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.
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.
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 Ebenennummer
substitute(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:
Über normalen Befehl:
Beispieleingabe:
Beispielausgabe:
quelle
Sie können von /programming//a/4224454/15934 bis Null Ihre Zahlen auffüllen.
Um das Auffüllen von Zahlen zu vereinfachen, würde ich zwei Funktionen und einen Befehl verwenden:
Wählen Sie dann Ihre Zeilen aus und geben
:PrependNumber
Sie ein (Sie werden sehen:'<,'>PrependNumber
. [Hinweis: Der Befehl verwendet einen optionalen Parameter: das Muster, vor dem die Zahl eingefügt wird]quelle
line(".")
"aktuelle Zeilennummer verwenden"? Das war mein Problem 1. mit früheren Antworten konnte ich finden.$HOME/vimfiles/plugin/whatevernameyouwish.vim
. Oder sogar Ihren$HOME/_vimrc
(Windows-Dateinamen), wenn Sie es vorziehen (beim ersten Mal). Wenn Sie nicht sicher sind, was $ HOME auf Ihrem Computer ist, fragen Sie vim, was es denkt ->:echo $HOME
:source
wenn das vim-Skript korrekt im richtigen Verzeichnis installiert ist ({rtp} / plugin oder {rtp} / ftplugin / {filetype} / ftplugin für filetypspezifische Plugins).:source
ist das, womit wir vor mehr als anderthalb Jahrzehnten spielen mussten.Sie können sich dem nähern, indem Sie ein Makro aufzeichnen. Beginnen Sie mit Ihrer Originaldatei und stellen Sie der ersten Instanz die Nummer voran.
Bewegen Sie den Cursor auf
01
, wählen Sie ihn aus und ziehen Sie ihn mityiw
. Jetzt möchten Sie Ihre Aktionen von diesem Punkt aus aufzeichnen.qq/^Level 1<CR>P<C-A>A<space><esc>0yiwq
qq
Starten Sie ein Makro in Register q/^Level 1<CR>
Suchen Sie nach einer Zeile, die mit "Level 1" beginnt.P
vor dem Cursor einfügen (enthält Ihre Nummer)<C-A>
erhöht die NummerA<space><esc>
Fügen Sie nach der Nummer ein Leerzeichen ein0
Gehen Sie zum Startyiw
Ziehen Sie die aktuelle Nummerq
Beenden Sie das MakroWiederholen Sie dieses Makro dann mit
@q
.quelle
<C-A>
Kontrolle + a? Damit wird alles in Vim unter Windows ausgewählt.