2016-09-21 9 views
2

Ich habe vor kurzem über reguläre Ausdrücke gelernt. Ich versuche, FDF-Objekte in einzelne Strings zu sammeln, die ich dann parsen kann. Das Problem, das ich habe, ist, dass mein Code nur dem ersten Vorkommen entspricht und alle anderen "Objekte" in der FDF-Datei ignoriert werden.C# Regex passt nicht mehrmals

Objekte beginnen in einer eigenen Zeile mit 2 Zahlen und der Zeichenfolge "obj" und dann einem Wagenrücklauf (kein Zeilenvorschub). Sie enden nach einem Wagenrücklauf und der Zeichenfolge "endobj".

//testing parsing into objects... 
List<String> FDFobjects = new List<String>(); 

String strRegex = @"^(?<obj>\d+ \d+) obj\r(?<objData>.+?)\rendobj(?=\r)"; 
Regex useRegex = new Regex(strRegex, RegexOptions.Multiline | RegexOptions.Singleline); 

StreamReader reader = new StreamReader(FileName); 
String fdfString = reader.ReadToEnd(); 
reader.Close(); 

foreach (Match useMatch in useRegex.Matches(fdfString)) 
    FDFobjects.Add(useMatch.Groups["objData"].Value); 

if (FDFobjects.Count > 0) 
    Console.WriteLine(FDFobjects[0]); 

Console.WriteLine(FDFobjects.Count); 

(Ich war mit $ am Ende des Regex Zeichenfolge, aber das entspricht 0 mal, während mit (= \ r) paßt einmal?).

Edit: Einige Zeilenumbrüche sind CR/LF, und einige sind nur CR. Ich weiß nicht, ob es für die verschiedenen Teile der Datei immer konsistent ist, also überprüfe ich einfach auf alle. Ich habe mich auf das Folgende festgelegt, das bisher perfekt funktioniert (und ich verwende die Multiline-Option nicht). Das Hinzufügen der Blick hinter ist, was der größte Unterschied hier gemacht ....

... = new Regex(@"(?<=^|[^\\](\r\n|\r|\n))(?<objName>\d+ \d+) obj(\r\n|\r|\n)(?<objData>.*?)(?<!\\)(\r\n|\r|\n)endobj(?=\r\n|\r|\n|$)", RegexOptions.Singleline); 
+0

Try '@ "^ (? \ d + \ d +) obj \ r? \ N (? . +?) \ R? \ Nendobj (? = \ R? \ N)"'. Vielleicht kann es helfen, '\ r' zu einem flexibleren' \ r? \ N' zu ändern. Ohne einen genauen Beispielstring ist es nicht einfach, Ihnen bei diesem Muster zu helfen. –

+0

@Wiktor: Danke. Es funktioniert nicht. Das FDF verwendet nur Wagenrücklauf nur, es scheint. – someprogrammer

+1

Geben Sie dann die genaue Eingabezeichenfolge mit exakt erwarteter Ausgabe an. –

Antwort

0

Die ^ in Ihrem Muster wird nur zu Beginn der Zeichenfolge übereinstimmen. Versuchen Sie \b stattdessen.

+2

Das erste Objekt steht nicht am Anfang der Zeichenfolge und stimmt überein. Die Option RegexOptions.Multiline soll die Übereinstimmung von^und $ ändern. – someprogrammer

+0

Guter Punkt ... Ich habe noch nie zuvor 'Singleline' und' Multiline' gemischt versucht - brauchen Sie wirklich beides? – dahlbyk

+1

Ich höre dich. Die unglücklichen Namen "Singleline" und "Multiline" sind nicht miteinander verknüpft. "Singleline" hat damit zu tun, ob der Punkt mit neuen Zeilen übereinstimmt oder nicht. – someprogrammer

0

Es scheint, dass MSDN Regex Web help liegt, was ^ Spiele:

^   -     Spiele die Position am Anfang der gesuchten Zeichenfolge. Wenn das Zeichen m (mehrzeilige Suche) in den Flags enthalten ist, entspricht ^ auch der Position, die auf \n oder \r folgt.

Sie paßt nur die Position nach\n siehe following demo mit dem @"(?m)^\d+" Musteranpassungs 1, 2, 4 im "1\r\n2\r3\n4" Eingang (3 mit \r voran).

Verwendung (?<=\r|^) am Anfang und am Ende (?=\r|$):

var s = "1 2 obj\rObj1\rendobj\r2 3 obj\rObj2\rendobj\r3 45 obj\rObj3\rendobj"; 
var matches = Regex.Matches(s, @"(?<=\r|^)(?<obj>\d+ \d+) obj\r(?<objData>.+?)\rendobj(?=\r|$)", 
     RegexOptions.Multiline | RegexOptions.Singleline); 
foreach (Match m in matches) 
{ 
    Console.WriteLine("___ MATCH ___"); 
    Console.WriteLine(m.Value); 
} 

Ausgänge alle 3 Treffer:

___ MATCH ___ 
1 2 obj 
Obj1 
endobj 
___ MATCH ___ 
2 3 obj 
Obj2 
endobj 
___ MATCH ___ 
3 45 obj 
Obj3 
endobj 

die C# demo online See.

+0

Danke für die Eingabe. Es sieht so aus, als ob die Multiline-Option nicht so funktioniert, wie sie sollte, aber ich erinnere mich nicht an die Details. (Ich habe seitdem geschlafen.) – someprogrammer

+0

Diese Option ist ziemlich schwierig. Ich dachte, ich hätte es gut gewusst, aber deine Frage war ein Augenöffner :) –