AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

TPerlRegEx - stack overflow

Ein Thema von liftoff · begonnen am 12. Jun 2012 · letzter Beitrag vom 14. Jun 2012
Antwort Antwort
Seite 2 von 3     12 3   
liftoff

Registriert seit: 6. Jun 2012
Ort: Frankfurt am Main
11 Beiträge
 
Delphi XE Enterprise
 
#11

AW: TPerlRegEx - stack overflow

  Alt 13. Jun 2012, 14:02
Ja, gutes Näschen.

Es folgt am Anfang der letzten Zeile immer ein '-}'

Eine Swiftnachricht besteht aus mehreren Blöcken.
Code:
{1:...}{2:...}{3:...}{4:
Nachrichteinhalt
-}{5:}
Der Block 4 (Textblock) muss immer mit '{4:'+Zeilenumbruch anfangen und mit Zeilenumbruch+'-}' enden.

Blöcke 1+2 enthalten Adressinformationen (Absender+Empfänger), 3 Userinfos und 5 Checksummen und son Zeuchs. 1+3+5 sind optional.

Ich habe eben auch noch einen anderen funktionierenden Konstrukt gebastelt

Code:
{4:\R(?:[[:ascii:]]+\R)+-}
  Mit Zitat antworten Zitat
liftoff

Registriert seit: 6. Jun 2012
Ort: Frankfurt am Main
11 Beiträge
 
Delphi XE Enterprise
 
#12

AW: TPerlRegEx - stack overflow

  Alt 13. Jun 2012, 15:33
So. Nach einigen Tests habe ich mich für die non-greedy Variante entschieden.
Performance liegt bei etwa 22000 Nachrichten/h, also parsen, zerlegen und strukturiert in der DB ablegen.
Auf den produktiven Systeme geht das noch ne ganze Ecke flotter.
Ist zwar langsamer als vorher, jedoch vollkommen zufriedenstellend.
Nun lass ich die Bibliothek auf die anderen Prozesse los.

Dank Euch bis hierhin für die Hilfe.

@ele
Bin sehr zufrieden mit meinem Arbeitgeber. Aber vielleicht kann man sich ja auf fachlicher Ebene ein wenig austauschen.
Bei mir steht beispielweise demnächst die Erweiterung auf ISO20022 (XML) an.
  Mit Zitat antworten Zitat
Benutzerbild von MaBuSE
MaBuSE

Registriert seit: 23. Sep 2002
Ort: Frankfurt am Main (in der Nähe)
1.837 Beiträge
 
Delphi 10 Seattle Enterprise
 
#13

AW: TPerlRegEx - stack overflow

  Alt 13. Jun 2012, 17:18
Code:
...
    re.RegEx := '({4:\r\n(?:[^\r\n]*\r\n)*-})';
Hallo,
ich habe mit meinen RegEx Experten gesprochen.

Er sagt, Deine RegEx sieht so aus, als hättest Du den Unterschied zwischen greedy und non-greedy nicht richtig verstanden, als Du diese Expression erstellt hast. Es sieht so aus, als wolltest Du das non-greedy manuell erzwingen. Das macht die RegEx nur unnötig kompliziert.

Folgende Expression würde alles zwischen dem '{4:' und '-}' auswählen. Mit der non-greedy Option '?' die nach dem Wildcard '*' steht, wird das Ergebnis möglichst kurz gehalten.
Code:
...
    re.RegEx := '(\{4\:.*?-\})';
...
'{4: bla bla bla bla -}{4: bla bla -}'

-> '{4: bla bla bla bla -}' wird ausgewählt


Code:
...
    re.RegEx := '(\{4\:.*-\})'; // ohne ? -> greedy
...

ohne ? -> greedy wird folgendes ausgewählt:

'{4: bla bla bla bla -}{4: bla bla -}'

Durch die Vereinfachung der RegEx ist es nicht nur einfacher zu lesen sondern es werden auch weniger rekursive Aufrufe nötig, also auch der Stack weniger beansprucht
Ich hoffe das hilft Dir weiter.

cu
MaBuSE

[edit]
Obiges Beispiel funktioniert natürlich nur wenn die SingleLine Option aktiv ist. Nur dann steht der '.' auch für ein '/n'.

Delphi-Quellcode:
...
// re.Options := [preCaseLess, preSingleLine];
// re.RegEx := '(\{4\:.*?-\})';

    // alternativ kann man die Optionen auch in die RegEx schreiben:
    // '?' -> jetzt kommen Optionen -> 's' = SingleLine ; 'i' = CaseLess -> ':' = Optionen Ende
    re.Options := [];
    re.RegEx := '(?si:\{4\:.*?-\})';
...
Habe ich ausprobiert funktioniert.
[/edit]

[edit] Beispiel:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

uses
  RegularExpressionsCore;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var re : TPerlRegEx;
    teststr : UTF8String;
    l1 : integer;
begin
  try
    re := TPerlRegEx.create;
    re.State := [];
    re.Options := [];
    re.RegEx := '(?si:\{4\:.*?-\})';
    re.Compile;

    // Nun Beispielstring mit Inhalt
    // {4:
    // :00X:ABCDEFB0123456789
    // :00X:ABCDEFB0123456789
    // -}
    // ...
    // {4:
    // :00X:ABCDEFB0123456789
    // :00X:ABCDEFB0123456789
    // -}
    // zusammenbauen

    TestStr := '{4:'+chr(13)+chr(10);
    for l1 := 1 to 2 do
    begin
      TestStr := TestStr + ':00X:ABCDEFB0123456789' +chr(13)+chr(10);
    end;
    TestStr := TestStr + '-}';
    TestStr := TestStr + TestStr + TestStr + TestStr;

    re.Subject := TestStr;

    if re.Match then
    begin
      Memo1.Lines.Add(re.MatchedText);
      Memo1.Lines.Add('-------------------');

      while re.MatchAgain do
      begin
        Memo1.Lines.Add(re.MatchedText);
        Memo1.Lines.Add('-------------------');
      end;
    end
    else
    begin
      Memo1.Lines.Add('Kein Treffer')
    end;

  except
    on E: Exception do
      Memo1.Lines.Add(E.ClassName+ ': '+ E.Message);
  end;
end;

end.
[/edit]
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)

Geändert von MaBuSE (13. Jun 2012 um 17:49 Uhr)
  Mit Zitat antworten Zitat
liftoff

Registriert seit: 6. Jun 2012
Ort: Frankfurt am Main
11 Beiträge
 
Delphi XE Enterprise
 
#14

AW: TPerlRegEx - stack overflow

  Alt 13. Jun 2012, 18:19
Wow. Danke fur die ausführliche Untersuchung.
Ich möchte, dass sich das nur matcht, wenn die unter #11 beschriebenen Kriterien zutreffen.
Also nach {4: ein Umbruch, danach Zeilen mit Egal plus Umbruch und danach eine letzte Zeile mit einem -} am Anfang.

So ganz habe ich aber in der Tat den Zusammenhang mit dem Stack noch nicht ergründen können.
  Mit Zitat antworten Zitat
Benutzerbild von MaBuSE
MaBuSE

Registriert seit: 23. Sep 2002
Ort: Frankfurt am Main (in der Nähe)
1.837 Beiträge
 
Delphi 10 Seattle Enterprise
 
#15

AW: TPerlRegEx - stack overflow

  Alt 14. Jun 2012, 11:55
Wow. Danke fur die ausführliche Untersuchung.
Gern geschehen. Übrigens willkommen in der DP

Ich möchte, dass sich das nur matcht, wenn die unter #11 beschriebenen Kriterien zutreffen.
Also nach {4: ein Umbruch, danach Zeilen mit Egal plus Umbruch und danach eine letzte Zeile mit einem -} am Anfang.
Dann solltest Du noch zusätzlich je einen Zeilenumbruch einfügen '/n'. re.RegEx := '(\{4\:/n.*?/n-\})';
So ganz habe ich aber in der Tat den Zusammenhang mit dem Stack noch nicht ergründen können.
Im Wesentlichen wird zwischen HEAP und STACK unterschieden. Auf Daten die auf den Stack gelegt werden kann man relativ schnell zugreifen, dafür ist die Stackgröße beschränkt. Auf Daten im Heap kann langsamer zugegriffen werden, dafür ist im Heap viel mehr Platz.

Parameter von Prozeduren und Funktionen werden auf dem Stack gespeichertund nach dem Ende der Funktion wieder freigegeben.
Bei einer Rekursion ruft sich eine Funktion selbst auf. Wenn eine Funktion sich z.B. 100 mal aufruft, dann wird auch 100 mal Stack für Parameter benötigt.

Ich hoffe das hilft Dir weiter.
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)
  Mit Zitat antworten Zitat
liftoff

Registriert seit: 6. Jun 2012
Ort: Frankfurt am Main
11 Beiträge
 
Delphi XE Enterprise
 
#16

AW: TPerlRegEx - stack overflow

  Alt 14. Jun 2012, 12:25
Nene. Stack und Heap, hab ich lieb. Damit kenne ich mich schon aus.

Nur den Zusammenhang zwischen greedy und lazy im Zusammenhang mit dem PCRE-Stack hab ich nicht verstanden.

Hier ein glaube ich altes Beispiel.

banane

b(an)+ liefert 'banan'

b(an)+? liefert der Faulheit wegen nur noch 'ban'

Hänge ich dem Ausdruck ein e an

b(an)+?e

liefert das 'banane'. Er ackert also den Match mit (an)+? zwei Mal durch.

Genauso verhält es sich mit meinem Ausdruck ganz oben. Nur statt 'an' eben einzelne Zeilen mit einem Umbruch am Ende.

Wieso liefert greedy einen stack overflow und lazy keinen. Die X Zeilen muss er in beiden Fällen durchlaufen.

Meinste statt /n vielleicht nicht eher \n ?
Statt \n nehme ich \r\n, also einen Windows-Umbruch #13#10.
  Mit Zitat antworten Zitat
Benutzerbild von MaBuSE
MaBuSE

Registriert seit: 23. Sep 2002
Ort: Frankfurt am Main (in der Nähe)
1.837 Beiträge
 
Delphi 10 Seattle Enterprise
 
#17

AW: TPerlRegEx - stack overflow

  Alt 14. Jun 2012, 12:38
Wieso liefert greedy einen stack overflow und lazy keinen. Die X Zeilen muss er in beiden Fällen durchlaufen.
Sorry, hab dich falsch verstanden.
In Deiner XE Ent. Version sind ja alle Quelltexte enthalten.
IN Projektoptionen Debug-DCUs anschalten und einfach mal in die Match Methode reindebuggen

Meinste statt /n vielleicht nicht eher \n ?
Statt \n nehme ich \r\n, also einen Windows-Umbruch #13#10.
Stimmt
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
9.846 Beiträge
 
Delphi 11 Alexandria
 
#18

AW: TPerlRegEx - stack overflow

  Alt 14. Jun 2012, 14:34
In Deiner XE Ent. Version sind ja alle Quelltexte enthalten.
IN Projektoptionen Debug-DCUs anschalten und einfach mal in die Match Methode reindebuggen
Die PCRE-Implementation liegt zwar als C-Source vor, wird aber von Delphi als vorcompilierte OBJ-Dateien (ohne Debug-Info) eingelinkt. Leider gestaltet sich das Debuggen so etwas schwieriger als gewohnt.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
ele

Registriert seit: 18. Feb 2009
129 Beiträge
 
Delphi 2010 Professional
 
#19

AW: TPerlRegEx - stack overflow

  Alt 14. Jun 2012, 14:51
Folgende RegEx funktioniert:

Code:
({4:\r\n(?:[^\r\n]*\r\n)*?-})
Ich habe keine Ahnung von SWIFT (zumindest nicht im Detail), aber der reguläre Ausdruck ist definitv nicht richtig.

- Geschweifte Klammern haben in pcre eine spezielle Bedeutung (Quantifizierung) und müssen daher escaped werden, wenn man sie matchen möchte
- Das Fragezeichen vor der Klammer ist auch fragwürdig, denn es ist ein Quantifizierer also ein Kürzel für {0,1} und ein vorhergehendes Char, Set oder Gruppe fehlt demnach
Du hast recht, es ist besser die geschweiften Klammern zu escapen. Trotzdem ist es eine absolut gültige RegEx:

Zitat von http://perldoc.perl.org/perlre.html:
If a curly bracket occurs in any other context and does not form part of a backslashed sequence like \x{...} , it is treated as a regular character.
Zur aktuellen Diskussion:
Das debuggen von PCRE willst du dir nicht antun - selbst wenn der code in Delphi geschreiben wäre. Regular Expression Engines sind ein ziemlich komplizierte Dinger und die PCRE ist ein Monster. Da schreibst du lieber deinen eigenen Parser - das benötigt weniger Zeit.
  Mit Zitat antworten Zitat
WladiD

Registriert seit: 27. Jan 2006
Ort: Celle
133 Beiträge
 
Delphi 10.4 Sydney
 
#20

AW: TPerlRegEx - stack overflow

  Alt 14. Jun 2012, 15:25
Du hast recht, es ist besser die geschweiften Klammern zu escapen. Trotzdem ist es eine absolut gültige RegEx:
Zitat von http://perldoc.perl.org/perlre.html:
If a curly bracket occurs in any other context and does not form part of a backslashed sequence like \x{...} , it is treated as a regular character.
Ja, du hast Recht, das habe ich im Nachhinein auch erfahren. Ich persönlich escape generell alle Zeichen, die irgendeine anderweitige Bedeutung im Ausdruck haben, so ist man auf der sicheren Seite. Vor allem wenn man den Punkt an sich matchen möchte, sollte man ihn tunlichst nicht vergessen zu escapen

Zur aktuellen Diskussion:
Das debuggen von PCRE willst du dir nicht antun - selbst wenn der code in Delphi geschreiben wäre. Regular Expression Engines sind ein ziemlich komplizierte Dinger und die PCRE ist ein Monster. Da schreibst du lieber deinen eigenen Parser - das benötigt weniger Zeit.
Keine Software ist perfekt, aber die PCRE halte ich für eines der solidesten Projekte, die die IT-Branche zu bieten hat. Sodass man zuerst an der eigenen Expression zweifeln sollte, bevor man einen Bug in der PCRE vermutet.
Waldemar Derr
Profil bei GitHub
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:43 Uhr.
Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf