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]