Wie füge ich sich wiederholenden Text mit geringfügigen Unterschieden in vim ein?

11

Ich möchte folgenden Text einfügen:

similar text wordA similar text ...
similar text wordB similar text ...
similar text wordC similar text ...

Ich weiß, dass ich den Text viele Male einfügen und dann die Ersetzung verwenden kann, um ein einzelnes Wort für jede Zeile zu ändern, aber ich finde diese Methode immer noch sehr unpraktisch.

Gibt es eine Möglichkeit, ein Wort oder eine Wortliste in einer "Variablen" zu speichern und diese Variable dann zu verwenden, um ähnlichen Text zu generieren?


BEARBEITEN Ich habe in der ursprünglichen Frage etwas Unklares gemacht. Tatsächlich versuche ich, einige sehr ähnliche Funktionsdefinitionen zu erstellen. wordA wordBDaher kann ... in jedem Textklon viele Male vorkommen und der Text kann viele Zeilen enthalten. Das Muster ist genau so:

similar_text1 wordA similar_text2 wordA similar_text3 ...
similar_text1 wordB similar_text2 wordB similar_text3 ...
similar_text1 wordC similar_text2 wordC similar_text3 ...

(Text kann neue Zeilen enthalten und WortA, WortB ... kann viele Male existieren)


2. BEARBEITUNG Die Teile "ähnlich_text" können jedes Mal anders sein, wenn ich einen solchen Job mache. Daher ist es besser, die Lösung für diesen Job wiederverwendbar zu machen. Weil ich versuche, sehr ähnliche Funktionsdefinitionen oder eine Zeichenfolge zur Funktionszuordnungstabelle zu erstellen.

Nach dem Lesen von Antworten und einigen Übungen finde ich es bequemer, diesen Job als eine Art Substitution zu betrachten, da es schwierig ist, separate "part1", "part2" ... "partN" zu schreiben, die möglicherweise Zeilenumbrüche enthalten. Schreiben Sie also eine Vorlage zuerst:

similar_text1 $WORD similar_text2 $WORD similar_text3 ...
(text may contain <ENTER>, make sure $WORD not exist in "similar_text" parts )

Dann ist der Versuch, Klone des Textes zu platzieren, aber $ WORD durch eine Liste von Wörtern zu ersetzen, klarer.

Mein Problem scheint sich also dahingehend geändert zu haben, "wie man einen Textblock viele Male klont, aber jedes Mal, indem man ein Schlüsselwort darin durch ein Wort aus einer Liste ersetzt".

social_loser
quelle
Deshalb werden Register für verwendet. Sie können Text in ein Register ziehen (kopieren) und dieses Register dann verwenden. Makros können sowohl für ähnliche als auch für sich wiederholende Aufgaben verwendet werden.
SibiCoder

Antworten:

7

Sie können die folgende Funktion verwenden:

function! GenerateLines()
    let firstpart="similar text part 1"
    let secondpart="similar text part 2"

    let words=["wordA","wordB","wordC","wordD","wordE"]

    for word in words
        let line = firstpart . word . secondpart
        call append(line('.')+1, line)
        normal j
    endfor
endfunction

Geben Sie in die Variablen firstpartund secondpartden Text, der vor und nach den Wörtern wiederholt werden soll, und in die Liste wordsdie Wörter ein, die sich ändern sollen.

Dann erstellt die Schleife den Inhalt der Zeile für jedes Wort der Liste, fügt die Zeile in den Puffer ein und wechselt zu dieser neuen Zeile.

Sie können dann einfach die Funktion aufrufen : call GenerateLines().


Bearbeiten Um die Manipulation zu vereinfachen, können Sie die verschiedenen Teile auch als Argumente übergeben. Die Funktion sollte folgendermaßen aussehen:

function! GenerateLines(firstpart, secondpart, words)
    for word in a:words
        call append(line('.')+1, a:firstpart . word . a:secondpart)
        normal j
    endfor
endfunction

Und Sie können es so nennen:

call GenerateLines("first part", "second part", ["wordA","wordB","wordC","wordD","wordE"])
statox
quelle
Sie könnten die Schleife mit call map(a:words, 'a:firstpart . v:val . a:secondpart')und vermeiden call append(line('.'), a:words).
Antony
Da ich solche Bearbeitungen oft mit sehr langen "ersten Teilen" und "zweiten Teilen", sogar "dritten Teilen", vornehme und diese Teile möglicherweise Zeilenumbrüche enthalten, scheint es zu lang zu sein, so viel im Befehlsmodus einzugeben, also ist es vielleicht praktischer Text in Register ziehen und dann Funktionen verwenden, um Text aus Registern zu generieren?
social_loser
Ich habe die Frage bearbeitet, sie ändert sich sehr, entschuldigen Sie die Unannehmlichkeiten.
social_loser
5

Meine Strategie in solchen Fällen variiert, folgt jedoch häufig den folgenden Schritten:

  1. Schreiben Sie die eindeutigen Wörter, z

    wordA
    wordB
    ...
    wordK
    
  2. Entweder

    a) Suchen und Ersetzen, z

    :%s/\w\+/similar text \0 similar text .../
    

    b) oder verwenden Sie den visuellen Blockmodus, siehe :h blockwise-visual. Insbesondere werde ich die Wörter auswählen und verwenden I, um ähnlichen Text vorne einzufügen oder Aähnlichen Text danach anzuhängen.

Ich würde argumentieren, dass diese Strategie sinnvoll ist, wenn Sie diese Art von Bearbeitungsaufgabe relativ selten ausführen. Wenn Sie jedoch feststellen, dass Sie dies häufig tun müssen, sollten Sie dem Vorschlag von @ statox mit einer Funktion folgen, die die Liste der Wörter erweitert.

Karl Yngve Lervåg
quelle
Ich denke, die Lösung hängt davon ab, woher die Wortliste kommt. Wenn es aus einer Datei stammt, :readist es sehr sinnvoll , gefolgt von Ihrer Ersetzung.
Antony
Ihre Lösung ist einfach zu tun und das Problem, das ich in der ursprünglichen Frage gestellt habe, leicht zu lösen. Es gibt jedoch einige Fehler in meinem ursprünglichen Beitrag, ich habe 2 Änderungen vorgenommen und es ändert sich sehr, danke für die Antwort, Entschuldigung für mein sich änderndes und schlechtes Englisch :)
social_loser
@social_loser Sie können diese Lösung anpassen, indem Sie "\ r" verwenden, um für eine neue Zeile im Ersatzteil der Substitution zu stehen
frangio
2

Ich werde argumentieren, dass dies ein Job für den visuellen Block ist ( Ctrl+ v). Zuerst würde ich alle unterschiedlichen Wörter schreiben:

wordA
wordB
wordC
wordD
wordE

Beginnend mit dem Cursor auf dem ersten wwürde ich dann ausführen:

<c-v>5j$yA <esc>pA <esc>p

Ich kann steuern, wie viele Spalten ich benötige, indem ich A <esc>pso oft drücke, wie ich möchte. Nehmen wir an, ich brauchte drei Spalten, wie der obige Befehl zeigt. Jetzt haben wir folgendes:

wordA wordA wordA
wordB wordB wordB
wordC wordC wordC
wordD wordD wordD
wordE wordE wordE

Und der Cursor steht am Anfang des 3. wordAin der ersten Zeile. Als nächstes würde ich die Auswahl der Leerzeichen-Spalte zwischen den rückwärts gehenden Spalten blockieren und den dazwischen liegenden Text hinzufügen. Von der aktuellen Cursorposition:

h<c-v>5jI similar text 3<esc>

Dies führt zu (das% markiert die Cursorposition):

wordA wordA%similar text 3 wordA
wordB wordB similar text 3 wordB
wordC wordC similar text 3 wordC
wordD wordD similar text 3 wordD
wordE wordE similar text 3 wordE

Wiederholen Sie dies für die nächste Spalte:

bh<c-v>5jI similar text 2<esc>

Und die letzte / erste Spalte (die auf der linken Seite):

b<c-v>5jIsimilar text 1 <esc>

Schließlich ergibt sich:

similar text 1 wordA similar text 2 wordA similar text 3 wordA
similar text 1 wordB similar text 2 wordB similar text 3 wordB
similar text 1 wordC similar text 2 wordC similar text 3 wordC
similar text 1 wordD similar text 2 wordD similar text 3 wordD
similar text 1 wordE similar text 2 wordE similar text 3 wordE

Update: Screencast hinzugefügt

Geben Sie hier die Bildbeschreibung ein


Dies scheint viel Tippen zu sein, aber es ist eigentlich sehr einfach, sich daran zu gewöhnen. Sie haben die Freiheit, die Anzahl der Wörter, die Anzahl der Spalten und sogar den Abstand zwischen den Spalten zu ändern.

Der Nachteil ist, dass Sie die Anzahl der verwendeten Wörter kennen müssen . Ich habe 5in allen obigen Befehlen eine feste Codierung, da dies die Anzahl der Zeilen ist, mit denen die Befehle ausgeführt werden.

Hinweis zum Debuggen: Alle Befehle beginnen und enden im normalen Modus. Wenn Sie sich am Ende eines Befehls im visuellen Modus oder im Einfügemodus befinden, machen Sie etwas falsch.

gro♀
quelle