Wie ersetze ich Inhalte zwischen zwei Mustern aus der Datei?

9

Ich habe das folgende Format der Datei:

<common>
fitnes=0
genetic=1
method=0
</common>
<inputs>
foo=bar
bar=foo
</inputs>
<limits>
balance=200.00
</limits>

und ich möchte alles löschen, was zwischen <inputs>und liegt </inputs>(ausgenommen Muster selbst) und es durch den Inhalt einer anderen Datei ersetzen (z foo.txt. B. ). Mit anderen Worten, Zeilen mit foo=barund bar=foowürden durch einen anderen Inhalt ersetzt.

Wahrscheinlich kann es ähnlich sein, wie Sie eine mehrzeilige Übereinstimmung löschen , wie zum Beispiel:

:g/<inputs/,/inputs>/d

Ich bin mir aber nicht sicher, durch was ich das ersetzen soll d, um den Inhalt einer anderen Datei einzufügen, aber ich möchte das passende Muster beibehalten.

Ein ähnlicher Ansatz wäre, den inneren Inhalt des HTML-Tags zu entfernen , wie z

:/<inputs>/norm vitd

aber dann weiß ich nicht, wie Sie den Inhalt aus der Datei hinzufügen würden.

Im Idealfall versuche ich, einen Liner zu finden, da dieser Teil eines anderen Skripts ist.

Wie kann ich das erreichen?

Kenorb
quelle

Antworten:

10

Eine Substitution kann verwendet werden, um ein Muster durch das Ergebnis eines Ausdrucks wie diesen zu ersetzen:

:keeppatterns %s;<inputs>\zs\_.\{-}\ze</inputs>;\=insert(readfile('test.txt'), '')

Sehen :help sub-replace-expression

Beachten Sie, keeppatternsdass der substituteBefehl nichts zum Suchverlauf hinzufügt und das "letzte Suchmusterregister" beibehält - siehe :help "/. Es ist eine gute Übung Skripte zu verhindern , dass unnötig mit den Befehlsoptionen Vims globalen Zustand zu modifizieren keepalt, keepjumps, lockmarks, keepmarks, und keeppatterns.

djjcast
quelle
5

Ein alternativer Ansatz zu dem von Gary ist folgender:

:g/^<inputs>/+,/^<\/inputs>/-d|-r dummy

Was zuerst alles in dem gegebenen Muster löscht, dann verwendet der :rBefehl, um die Daten aus dem Datei-Dummy zu lesen. Wenn Sie nun den Dateinamen aus den Linien zwischen den <input>/</input>Mustern extrahieren müssen , wird es etwas komplizierter.

Christian Brabandt
quelle
4

Dies scheint zumindest auf einem Unix-System zu funktionieren:

:/<inputs>/+1,/<\/inputs>/-1!cat foo.txt

Mit dem {range}!{filter}Befehl werden die Zeilen durch das externe Programm von eins nach <inputs>dem anderen gefiltert . In diesem Fall wird die Standardeingabe ignoriert, sodass die ursprünglichen Zeilen gelöscht und durch den Inhalt der Datei ersetzt werden .</inputs>cat foo.txtcatfoo.txt

Sehen:

:help :range!
:help cmdline-ranges
Garyjohn
quelle
2

Ich denke, ein Makro wird ein einfacherer Ansatz sein. Vor allem, wenn Sie verschiedene Orte haben, an denen Sie dasselbe tun können.

  1. Lassen Sie nur diese 2 Dateien offen.
  2. Starten Sie nun in der ersten Datei die Aufnahme mit qa,( aist der Name des Datensatzes).
  3. Suchen Sie nach dem Startmuster, drücken Sie nach unten und dann Ctrl- v, suchen Sie nach dem Endmuster und drücken Sie nach oben . Nun wird der Teil ausgewählt, den Sie löschen möchten. Lösche es.
  4. Markieren Sie die Position mit ma( aist der Markenname) und speichern Sie die Datei.
  5. Gehen Sie per :b2Befehl zur zweiten Datei und wählen Sie das Teil auf ähnliche Weise gemäß Ihren Start- / Endkriterien aus.
  6. Kommen Sie zurück zu dieser Datei und drücken Sie a, um zu diesem Punkt zu gelangen. Dort einfügen durch p.
  7. Suchen Sie erneut nach Endkriterien und durchqueren Sie den Abschnitt, um ihn nicht erneut zu treffen.
  8. Beenden Sie die Neukodierung durch Drücken von q.
  9. Wiederholen Sie die Anzahl bis 40@a.
Krishanu Banerjee
quelle
1
Vielen Dank für den Vorschlag, es ist in Ordnung, aber es hilft in diesem speziellen Fall nicht, da ich nach einer nicht interaktiven Lösung als Teil des exSkripts suche, in der ich abhängig von den Benutzereingabeargumenten angeben kann, welche Datei eingefügt werden soll.
Kenorb
1

Wenn dies ein weiterer Versuch ist, XML mit Nicht-XML-Tools zu analysieren, tun Sie dies nicht.

Die Lösungen hier sind gültig, aber die Absicht könnte nicht sein. Wenn das XML nicht aus einer gut gezähmten Quelle stammt, erhalten Sie möglicherweise Escape-, CDATA- oder Leerzeichen im Tag!

Xsltproc vom Befehl in vi kann damit umgehen.

Matthias Š
quelle
Die Datei hat nicht das richtige XML-Format, aber es ist keine gut dokumentierte iniDatei mit diesen 3 XML-ähnlichen Tags.
Kenorb