Autor Beitrag
Ares
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 128



BeitragVerfasst: Mo 15.03.10 15:57 
Hallo!

Ich verwende die Klasse TRegExpr von Andrey Sorokin um in Delphi Reguläre Ausdrücke nutzen zu können. Nun will ich Textdatei parsen die ähnlich einer normalen INI-Datei aufgebaut ist (nur das Format der Werte unterscheidet sich):

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
[Section1]
Werte...
Werte...
Werte...

[Section2]
Werte...
Werte...
Werte...


Beim Parsen der Datei will ich nun zunächst die einzelnen Sections herausfiltern und hierfür einen regulären Ausdruck verwenden. Bislang habe ich einen Ausdruck verwendet, der neben dem Section-Header auch direkt die einzelnen Werte zerlegt. Dieser war aber scheinbar zu komplex, denn bei der Anwendung auf sehr lange Werte kommt es beim Matching zu einem Stacküberlauf.

Ich suche daher nach einem einfachen Ausdruck, der mir eine Section mit den zugehörigen Werten zurück liefert. Umgangssprachlich wäre das einfach "Alles vom Sektion-Header bis zur nächsten Zeile in der erste Zeichen ein [ ist".

Das Problem ist, dass ich nicht weiß wie man "Suche alles was NICHT \r\n[ ist".

Eine bestimmte Zeichenkette zu suchen ist ja kein Problem, aber alles zu suchen was NICHT einer bestimmten Zeichenkette entspricht bekomme ich nicht hin.

Wie gebe ich also eine Zeichenkette als Suchmuster an und negiere diese? Geht das überhaupt?

Ich könnte natürlich einfach so vorgehen: "Suche Section-Header, dann beliebigen Inhalt bis nach einem Zeilenumbruch [ gefunden wird]". Hierbei ist aber das Problem, dass dann der Zeilenumbruch und die eckige Klammer zum ersten Match gehören. Starte ich dann die Suche nach dem nächsten Match sähe der Rest nur noch so aus: "Section2]...".

Das Ziel ist also:
Finde alle Inhalte bis zum Beginn einer neuen Section. Nimm hierbei aber nicht den Beginn der nächsten Section in den Match mit auf.


Ist das überhaupt möglich?

Besten Dank
Ares
Wolle92
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 1296

Windows Vista Home Premium
Delphi 7 PE, Delphi 7 Portable, bald C++ & DirectX
BeitragVerfasst: Mo 15.03.10 17:13 
du musst ja nicht gleich den kompletten match aus dem string rauspflücken...

ich kenne die TRegExpr-Klasse nicht, aber in PHP würd ich das ganze so machen:
ausblenden Quelltext
1:
preg_match_all('~(\[\w+\].*)\r\n\[~',$ini_content,$matches,PREG_SET_ORDER);					

dann hätte ich in matches ein mehrdimensionales Array, für jede Section ein Eintrag. In $matches[0][0] hätte ich den kompletten Match, in $matches[0][1] nur die Klammer.

Sowas sollte es doch in der TRegExpr auch geben, oder?
dann hätte ich noch nen besseren RegEx:
ausblenden Quelltext
1:
~\[(\w+)\](.*)\r\n\[~					

So würde ich das gleiche Muster suchen, hätte in den Match-Ergebnissen aber direkt Section-Name und die einzelnen Werte getrennt.

Wenn das so nicht funktioniert, nimmst du den ersten RegEx und entfernst nach der suche einfach nur das, was in der Klammer steht, aus dem ursprünglichen String.

Grüße,
Wolle

Edit: Ich weiß nicht, inwieweit das in Delphi implementiert ist, aber ansonsten wären lookarounds noch ne lösung:
ausblenden Quelltext
1:
~(?:\[(\w+)\](.*)\r\n)(?=\[)~					

Man korrigiere mich, sollte mir ein Fehler unterlaufen sein, RegExp sind nicht grade die einfachste Materie :P

Edit#2: Das Problem allgemein ist doch, das die letzte Section gar nicht mehr gematcht wird?
würde das gelöst durch:
ausblenden Quelltext
1:
~(?:\[(\w+)\](.*)\r\n)(?=[\[$])~					

Man beachte den Lookahead (?=[\[$]) um sowohl ne neue eckige Klammer als auch das Ende des Strings zu matchen.

_________________
1405006117752879898543142606244511569936384000000000.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 15.03.10 18:03 
Moin!

user profile iconAres hat folgendes geschrieben Zum zitierten Posting springen:
Ich verwende die Klasse TRegExpr von Andrey Sorokin um in Delphi Reguläre Ausdrücke nutzen zu können. Nun will ich Textdatei parsen die ähnlich einer normalen INI-Datei aufgebaut ist (nur das Format der Werte unterscheidet sich):
[...]
Beim Parsen der Datei will ich nun zunächst die einzelnen Sections herausfiltern und hierfür einen regulären Ausdruck verwenden.
Das Verarbeiten von regulären ausdrücken ist sehr aufwändig und deshalb unglaublich langsam, gerade wenn man große Mengen Quelldaten verarbeitet. :idea:

Bei so einer einfachen Aufgabe würde ich das nicht mit TRegExpr machen, das geht mit einer Stringliste und ein paar Zeilen Code sehr viel einfacher und vor allem schneller/resourcenschonender! :nixweiss:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Wolle92
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 1296

Windows Vista Home Premium
Delphi 7 PE, Delphi 7 Portable, bald C++ & DirectX
BeitragVerfasst: Mo 15.03.10 22:31 
Aber dafür haben reguläre Ausdrücke ein viel tolleres Aussehen! :P

_________________
1405006117752879898543142606244511569936384000000000.