Ich bin immer wieder erstaunt, was mit vim alles möglich ist. Auch wenn es mir unter Windows nicht ganz so fluffig von der Hand läuft wie Notepad++, so gibt es einfach Aufgaben, die einfach nicht anders machbar sind. Heute war wieder so ein AHA-Moment.
Folgenden Situation. Die erste Datei ist eine XML Datei die mittendrin mehreren Dutzend Datenzeilen hat, mit folgender Struktur (nur mir noch mehr "Feldern").
<id="00001" name="Viserys" alter="100">
<id="00002" name="Daemon" alter="100">
<id="00003" name="Rhaenyra" alter="100">
<id="00004" name="Alicent" alter="100">
Wie man sehen kann haben alle das Alter von 100.
Die zweite Datei kam aus einer Datenbank schön als CSV. Nach dem Löschen von unnötigen Spalten hatte ich folgendes:
26,0003
40,0002
26,0004
60,0001
Wie bekommt man jetzt das richtige Alter in das Feld in die XML ohne die Struktur der Datenzeilen und der gesamten XML zu zerstören?
Früher hätte ich alles irgendwie ins Excel gebracht, mit S-Verweis herumgedoktort, dann in Notepad++ die, dann Tab getrennten Einträge aus Excel, bereinigt und am Ende alle anderen Daten vor und nach den Einträgen per Copy&Paste wieder rangetackert.
Ein Python Skript zu schreiben war mir zu aufwändig, denn es waren insgesamt keine hundert Einträge. Da einen kompletten Parser zu bauen... Nein.
Mir kam die Idee das mit vim Makros zu lösen aber es sind ja zwei Dateien. Und dann kam mir die Idee, was ist wenn das Makro auch mehrer Tabs in vim steuern kann? Und nach einem kurzen Test hatte ich die Bestätigung, es geht. Also beide Dateien in vim in separaten Tabs öffnen und folgendes als Makro gespeichert.
- Sprung an den Anfang der Zeile
0
- Suche Eintrag id
[ESC]:/id[Return]
- Zwei Worte vorwärts und alles in den Anführungszeichen in den Zwischenspeicher lesen
2wvi"y
- In den Tab wechseln zu der Datei (das kann unterschiedlich bei jedem sein wegen der Reihenfolger der Tabs)
[STRG]+h
- Suche nach Eintrag aus dem Zwischenspeicher
[ESC]/[STRG]+r"[Return]
Damit ist man in der entsprechenden Zeile. Das ist der S-Verweis =)
- An den Anfang springen und das Alter in den Zwischenspeicher kopieren
[ESC]0yw
- Zurück in die XML Datei
[STRG]+l
- Den Eintrag "alter" suchen
[ESC]/alter[Return]
- Zwei Wörter vorwärts alles in Anführungszeichen markieren und durch den Inhalt des Zwischenspeicher ersetzen
2wvi"p
- Und damit man mit der nächsten Zeile weitermachen kann enden die Makros eigentlich fast immer mit "runter" und an den Anfang der Zeile
[ESC]j0
Und das war's. An drei Zeilen getestet und als gut befunden. Und dann mit
100@a[Return]
der Magie zugeschaut wie es blitzt und blinkt und alles wie gewünscht aufgeräumt wird. Klar muss man aufpassen das nicht weitere "id" Einträge irgendwo sind (mein Feldnamen war eindeutiger).
Man kann es aber auch Zeile für Zeile ausführen und trotzdem einen haufen Zeit sparen.
Vim Makros sind das Beste.