So kopieren Sie jede Zeile 11 Mal und erhöhen die letzte „1“ in jeder Zeile von 2-12

9

Ich habe eine Anzahl von Zeilen in einer Datei, und ich möchte jede Zeile 11 Mal kopieren (jede Zeile in 12 Zeilen umwandeln) und die letzte "1" in jeder Zeile erhöhen, sodass die 12 Zeilen "1" bis "haben". 12 ", wo die" 1 "ursprünglich war. Es kann andere Vorkommen von "1" in jeder Zeile geben, aber die "1", die ich erhöhen möchte, ist immer das letzte Vorkommen in jeder Zeile. Eine andere Sichtweise ist, dass die letzte "1" immer nach "/ nt /" steht - wie in "/ nt / 1" (und es wird immer das einzige Vorkommen von "/ nt / 1" in jeder Zeile sein) .

Also zum Beispiel, wenn ich habe:

1stlineblahblahblah/nt/1blah
2ndlineblahblahblah/nt/1blah
3rdlineblahblahblah/nt/1blah

Ich möchte daraus machen:

1stlineblahblahblah/nt/1blah
1stlineblahblahblah/nt/2blah
1stlineblahblahblah/nt/3blah
1stlineblahblahblah/nt/4blah
1stlineblahblahblah/nt/5blah
1stlineblahblahblah/nt/6blah
1stlineblahblahblah/nt/7blah
1stlineblahblahblah/nt/8blah
1stlineblahblahblah/nt/9blah
1stlineblahblahblah/nt/10blah
1stlineblahblahblah/nt/11blah
1stlineblahblahblah/nt/12blah
2ndlineblahblahblah/nt/1blah
2ndlineblahblahblah/nt/2blah
2ndlineblahblahblah/nt/3blah
...

Ich hatte zuvor den Befehl gefunden:

:for i in range(0,12) | put ='1stlineblahblahblah/nt/'.i.'blah' | endfor

funktioniert für diesen Zweck, aber ich müsste diesen Befehl für jede Zeile manuell ausführen und jede Zeile selbst eingeben (oder kopieren und einfügen). Gibt es eine Möglichkeit, die bereits in der Datei enthaltenen Zeilen zu übernehmen und nur einen Befehl auszuführen, der jede Zeile in die von mir beschriebene Weise in zwölf Zeilen umwandelt?

Vielen Dank im Voraus an alle, die mir dabei helfen können. Ich wollte auch nur erwähnen, dass dies meine zweite Frage hier ist, und ich war erfreut, mehrere schnelle und effektive Lösungen für meine erste Frage erhalten zu haben, für die ich sehr dankbar war.

ablewasiereisawelba
quelle

Antworten:

8

Hier ist eine Substitution, die das Problem löst:

:%s/\(.*\)1\(.*\)/\=join(map(range(1, 12), 'submatch(1) . v:val . submatch(2)'), "\n")

Die Ersetzung entspricht jeder Zeile, die "1" enthält, und erfasst den Text vor {c1}und nach {c2}der letzten "1". Für jede Zeile abgestimmt, wobei der Bereich von Zahlen einer bis zwölf {n}ist kartiert zwölf Zeilen der Form zu schaffen {c1}{n}{c2}. Jede Gruppe von zwölf Zeilen ersetzt die zugehörige, ursprünglich übereinstimmende Zeile.

Siehe :h sub-replace-expression.

djjcast
quelle
2
Wow, großartiger einzeiliger Befehl. Ich erinnere mich, dass Sie auch für die erste Frage, die ich vor einigen Wochen gestellt habe, eine elegante einzeilige Lösung gefunden haben. Sehr gute Arbeit. Vielen Dank. Ich vermute auch, dass es eine Möglichkeit gibt, dies in die _vimrc-Datei einzufügen, damit ich einen leicht zu merkenden Befehl oder eine Funktion ausführen kann, ohne die gesamte obige Zeile einzugeben (oder durch die Liste der vorherigen Befehle scrollen zu müssen), aber Ich bin noch nicht genug mit der _vimrc-Syntax vertraut, um zu wissen, wie es geht.
ablewasiereisawelba
10

Sie könnten dies tun, indem Sie

  1. dann ein Makro aufnehmen
  2. Verwenden Sie den globalBefehl ex, um das Makro n- mal für jede Zeile in der Datei auszuführen .

Machen Sie nach dem Aufzeichnen des Makros die während der Aufnahme vorgenommenen Änderungen rückgängig. Andernfalls werden n + 1 zusätzliche Zeilen für die erste Zeile und n für aufeinanderfolgende Zeilen angezeigt.

Zeichnen Sie das Makro mit in das aRegister ein

qayyp$?\d<CR><C-A>q

Dies zeichnet den folgenden Befehl in register a( qa...q) auf:

  • yyp: Dupliziere die aktuelle Zeile
  • $: zum Zeilenende gehen
  • ?\d<CR>: Suche rückwärts nach einer einzelnen Ziffer
  • <C-A>: Inkrementiere die Ziffer unter dem Cursor um eins

Wenn das Makro aufgezeichnet wird, entfernen Sie die während der Aufzeichnung vorgenommenen Änderungen, indem Sie entweder ( uu) rückgängig machen oder die aktuelle Zeile ( dd) löschen . Wiederholen Sie dann das Makro 11(oder eine beliebige Anzahl von Malen) für jede Zeile in der Datei mit dem globalen Befehl:

:g//normal 11@a
jjaderberg
quelle
2
Es funktionierte! Sehr Schön. Danke. Ich hatte anfangs ein Problem mit der Strg-a-Markierung, anstatt alles hinzuzufügen, weil ich gVim in Windows verwende ... aber ich habe eine schnelle Suche durchgeführt und diesen Thread gefunden - stackoverflow.com/questions/289681/… - wo ich habe den Vorschlag verwendet, nnoremap <kPlus> <Ca> nnoremap <kMinus> <Cx> in _vimrc einzufügen, damit ich die Tasten "+" und "-" zum Addieren und Subtrahieren verwenden kann. Außerdem musste der globale Befehl für mich lauten: g // normal 11 @ a, aber das war leicht herauszufinden. Danke!
ablewasiereisawelba
6

Zwei Wege:

Verwenden Sie ein Makro!

Beginnen mit

1stlineblahblahblah/nt/1blah
2ndlineblahblahblah/nt/1blah
3rdlineblahblahblah/nt/1blah

Mit dem Cursor in der ersten Zeile

qqyyp$?\d<CR><Ctrl-a>q
10@q

Welches tut:

qq Starten Sie die Aufnahme eines Makros in das q-Register

yyp Ziehen Sie die aktuelle Zeile und fügen Sie sie unten ein

$?\d<CR> Gehen Sie zum Ende der Zeile und suchen Sie die erste Ziffer, die nach hinten schaut

<Ctrl-a> Erhöhen Sie die Anzahl

q Beenden Sie die Aufnahme des Makros.

Dies lässt Sie mit:

1stlineblahblahblah/nt/1blah
1stlineblahblahblah/nt/2blah
2ndlineblahblahblah/nt/2blah
2ndlineblahblahblah/nt/3blah

Mit dem Cursor in der zweiten Zeile. Wiederholen Sie dieses Makro einfach so oft wie gewünscht (wiederholen Sie es beispielsweise zehnmal mit 10 @ q). Wenn Sie diesen Prozess für jede Zeile automatisieren möchten, führen Sie ihn global für jede Zeile aus:

:g//normal 11@q

Alternativ mit einer neueren Version von vim: Fügen Sie die gewünschte Zeile beliebig oft ein, wählen Sie mit dem visuellen Block die Ziffer aus, die Sie erhöhen möchten, und drücken Sie g <Ctrl-a>. Dies sollte alle Zahlen im visuellen Block nach Ihren Wünschen erhöhen. Dies ist jedoch ein manueller Prozess.

Fruglemonkey
quelle
1
Super, ich wusste nichts über den g <c-a>Weg. Danke für das Teilen.
kba steht mit Monica
1
@fruglemonkey Der erste Teil Ihrer Antwort ist der gleiche wie der oben, aber trotzdem danke. Der zweite Teil funktioniert meiner Meinung nach nicht für mich (es sei denn, ich mache etwas falsch), daher darf ich nicht die richtige Version verwenden.
ablewasiereisawelba
5

Ich finde es am einfachsten, Makros für solche One-Shot-Aufgaben zu verwenden. Beginnen Sie einfach mit der Aufnahme eines Makros mit dem qNamen + des Registers und führen Sie die Aufgabe einmal aus. Ich sehe hier eine wiederholbare Aufgabe:

  • Wählen Sie die Zeile aus
  • Ruck
  • Einfügen (bringt Sie in die nächste Zeile)
  • Gehe zum Zeilenende
  • Geh ein Wort zurück
  • um eins erhöhen

Zeichnen Sie nun aim normalen Modus die erforderlichen Tastenanschläge zur Registrierung auf:

qayyp$b<c-a>.

Löschen Sie die Zeile erneut, um zu testen, ob die elfmalige Ausführung des Makros das richtige Ergebnis für eine Zeile ergibt:

11@a

Es tut! Lassen Sie uns also erneut rückgängig machen und den gesamten Prozess in einem zweiten Makro automatisieren b:

qb11@aj

Jetzt können Sie @bbis zum Ende der Datei ausführen und es sollte die gewünschte Ausgabe erzeugen. Es klingt kompliziert, ist es aber nicht, wenn Sie erst einmal an die typischen Bearbeitungsmuster gewöhnt sind.

kba steht bei Monica
quelle
Ich bin mir nicht sicher, ob ich etwas falsch mache, aber es scheint nicht zu funktionieren. Ich bin dem gefolgt, was Sie geschrieben haben, aber vielleicht habe ich etwas falsch verstanden oder etwas nicht richtig ausgeführt. (Ich erhalte die erste Nummer der Zeile inkrementiert, nicht die letzte Nummer der Zeile.) Vielen Dank für Ihre Antwort.
ablewasiereisawelba
3
Ich denke das erste Makro sollte sein qaVyp$b<c-a>. Oder besser einfach qayyp$b<c-a>.
Karl Yngve Lervåg
1
Danke, @ KarlYngveLervåg, du hast recht, ich habe das Makro repariert.
kba steht mit Monica
2
Argh :( danke, dass du gründlich bist @ablewasiereisawelba. Ich denke, das Makro qqyyp$?\d<CR><Ctrl-a>qvon @fruglemonkey und @jjaderberg ist besser, da es die letzte Nummer sucht. Ich werde es der Vollständigkeit halber ändern.
kba steht mit Monica
2
@kba Ich dachte nur, wenn sich jemand die Zeit und Mühe nimmt, meine Frage zu beantworten, könnte ich zumindest seine Lösung ausprobieren - selbst wenn ich bereits eine funktionierende Lösung von jemand anderem gefunden hätte. Ich schätze Ihre Bemühungen - und wenn Sie sich dadurch besser fühlen, sind Sie mir immer noch meilenweit voraus. :)
ablewasiereisawelba
2

Speichern Sie das folgende Makro und verwenden Sie es für jede Zeile:

qqyy11p/\/\zs1<CR><C-v>10jg<C-a>q

Der Hauptunterschied zu den anderen Antworten besteht darin, dass g<C-a>eine Spaltenauswahl verwendet wird, die jede Zeile mit einer anderen Nummer erhöht. Überprüfen Sie :help v_g_CTRL-Afür weitere Informationen. Ich habe auch verwendet \zs, um die Startposition des Musters so auszuwählen, dass der Cursor bei der Nummer nach der Suche stoppt.

Bitte beachten Sie, dass Sie eine aktuelle Version von Vim benötigen, damit dies funktioniert.

Vitor
quelle
1
@fruglemonkey schlug das ebenfalls vor . Es ist eine coole Funktion, obwohl sie seit 7.4.754 (für vim-Verhältnisse) ziemlich neu ist und noch nicht an alle Distributionen ausgeliefert wurde.
kba steht mit Monica
Verpasste es sorry
Vitor
1
@Vitor Ich habe gerade gVim 7.4, also glaube ich nicht, dass ich das tun kann, auf das g<C-a>@fruglemonkey und Sie Bezug genommen haben, aber danke, dass Sie geantwortet haben. Ich sollte beachten, dass beim Ausprobieren Ihres Makros - kurz bevor ich zum g<C-a>Teil komme - nicht das letzte "1" -Zeichen, das ich inkrementieren möchte, blockiert wird, sondern das Zeichen vor dem ersten "1" "Zeichen, das blockmarkiert wird. (Auch ich denke, es wäre yy11pund 10jim Makro, da ich 11 Zeilen hinzufügen möchte - für insgesamt 12.)
ablewasiereisawelba
1
Vielen Dank für Ihre Rückmeldung. Ich habe die Antwort entsprechend aktualisiert. Beschlossen zu verwenden \zs, aber ich könnte genauso gut einfach eine hinzugefügt haben lnach <CR>.
Vitor
1
Sie haben wahrscheinlich einige Einstellungen in Ihrem vimrc, die sich auf die Suche nach regulären Ausdrücken auswirken. Versuchen Sie es erneut, indem Sie Vim mit starten vim -u NONE. Ich habe das gerade gemacht und das funktioniert perfekt! Tatsächlich würde die Suche auf keinen Fall mit der ersten 1 übereinstimmen, da ein vorhergehender Schrägstrich erforderlich ist.
Vitor