2009-10-02 13 views
7

Ich habe viele Beispiele gefunden, um Text in Dateien mit Regex zu ersetzen. Es läuft jedoch alles auf zwei Versionen ab:
1. Iterieren Sie über alle Zeilen in der Datei und wenden Sie Regex auf jede einzelne Zeile an
2. Laden Sie die gesamte Datei.Mehrzeilige Regex-Suche in ganze Datei

Nr. 2 Ist nicht machbar mit "meine" Dateien - sie sind über 2GiB ...
Zu Nr. 1: Derzeit ist dies mein Ansatz, aber ich frage mich ... Was, wenn Sie sich bewerben müssen ein Regex, das mehr als eine Zeile umfasst?

+1

Es ist möglich, diese Daten in ein RDBMS zu laden? –

+0

Ich denke, Sie müssen Ihre Daten und Regex besser beschreiben, um einen anständigen Vorschlag zu bekommen. –

+0

ok. Kleine Klarstellung: Oft muss ich große csv-Dateien modifizieren. (z. B. Schalter Spalte 3 und 5) Ich habe festgestellt, dass ich mit regex und sed die erforderlichen Änderungen wirklich schnell anwenden kann. Allerdings "entwickle" ich und teste meine Regex mit dem Regulator, was zu "clr-regex" führt, die dann in sed-Syntax übersetzt werden müssen. Um dies zu vermeiden, habe ich ein kleines Tool (C#) geschrieben, mit dem ich den "clr-regex" in eine Datei übernehmen kann. NOW: Mit diesem Tool ist es nicht möglich, Regex über mehrere Zeilen zu erstrecken - denn ich mache den oben genannten Ansatz Nr. 1. Die obige Frage war etwas hypothetisch. – Nils

Antwort

2

Hier ist die Antwort:
Es gibt keine einfache Möglichkeit,

Ich fand eine StreamRegex-Class, die in der Lage sein könnte zu tun, was ich suche.
Von dem, was ich von dem Algorithmus fassen konnte:

  • Beginnen Sie am Anfang der Datei mit einem leeren Puffer
  • tun (
    • ein Stück der Datei zu dem
    • Puffer hinzuzufügen
    • wenn es eine Übereinstimmung in dem Puffer
      • Marke das Spiel
      • fallen alle Daten, die aus dem Puffer vor dem Ende des Spiels erschien
  • ), solange es noch etwas von der Datei links ist

diese Weise ist es nicht nessesary ist die vollständige Datei zu laden - oder zumindest die Chancen, die volle Datei in den Speicher zu laden, werden reduziert ...
Allerdings: Im schlimmsten Fall gibt es keine Übereinstimmung in der ganzen Datei - in diesem Fall wird die gesamte Datei in den Speicher geladen.

0

Vielleicht könnten Sie zwei Zeilen gleichzeitig laden (oder mehr, je nachdem, wie viele Zeilen Ihrer Meinung nach Ihre Übereinstimmungen überspannen) und sie überlappen, zB: Laden Sie die Zeilen 1-2, dann die nächste Schleifenladung Linien 2-3, die nächste Ladung 3-4; und machen Sie Ihre Multiline-Regexes über beide Linien kombiniert in jeder Schleife.

+0

Gute Idee, aber jede Zeile würde möglicherweise mehrfach regex'd sein. Man müsste mögliche Nebenwirkungen in Betracht ziehen. – Nils

+0

Hmm ja, du hast Recht. Vielleicht nur übereinstimmen, wenn das Match in der ersten Zeile beginnt (vor jeder Instanz eines Zeilenumbrüchens)? –

1

Regex ist nicht der Weg zu gehen, vor allem nicht mit diesen großen Mengen an Text. Erstellen Sie einen eigenen Parser:

  • lesen Sie die Datei Zeile für Zeile;
  • für jede Zeile:
    • Schleife durch die Leitung char von char die Verfolgung irgendwelcher Öffnungs-/Schließ Stringliterale
    • , wenn Sie begegnen ‚/ *‘ (und du bist nicht ‚innen‘ eine Zeichenfolge), Shop, um die erste ‚* /‘ bis zur Hausnummer und Loop-Offset auftreten und diese Zahl speichern sowie

, dass Sie alle Start- und Schließ-Offset numbe geben rs der Kommentarblöcke. Sie sollten nun in der Lage sein, sie zu ersetzen, indem Sie eine temporäre Datei erstellen und den Text aus der ursprünglichen Datei in die temporäre Datei schreiben (und etwas anderes schreiben, wenn Sie sich in einem Kommentarblock befinden).

Edit: Quelldateien von 2GiB ??

+0

Habe ich Quelle gesagt? ;-) Keine "rohen" Daten, csv in der Tat. – Nils

+0

Ah, ich verstehe. Ich kenne C# nicht, würde mir aber vorstellen, dass so große Quelldateien nicht einmal erstellt werden können. –

0

Ich würde sagen, dass Sie die Daten vor der Ersetzung der Daten vorab analysieren/normalisieren sollten, so dass jede Zeile einen möglichen Datensatz beschreibt, der ersetzt werden muss. Andernfalls gerät man in Schwierigkeiten mit der Datenintegrität, die ohne eine Menge anderer Schwierigkeiten nicht wirklich gelöst werden kann.

Wenn es eine Möglichkeit gibt, die Daten in logische Blöcke zu zerlegen, könnten Sie ein Programm erstellen, das ein Mapreduce-Muster zum Parsen der Daten verwendet.

0

Ich bin mit Bart; Sie sollten wirklich eine Art von Parser dafür verwenden.

Oder, wenn Sie nichts dagegen haben, ein Kind Prozess Laichen, können Sie nur verwenden sed (es gibt eine native port on windows, oder Sie können Cygwin verwenden)

0

Wenn es Ihnen nichts ausmacht, Ihre Hände ein wenig schmutzig zu machen (und Ihre Regex ist einfach genug, oder vielleicht haben Sie ein starkes Verlangen nach Geschwindigkeit und nichts dagegen, ein bisschen leiden), können Sie Ragel verwenden. Es kann auf C# zielen, obwohl die Seite es nicht erwähnt. Sie müssen einen FileStream umschließen, um einen gepufferten Indexer bereitzustellen, oder eine Speicherabbilddatei (mit unsicheren Zeigern) in einem 64-Bit-Prozess verwenden, um dies jedoch mit großen Dateien zu verwenden.