Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Regex geht nicht mehr? (https://www.delphipraxis.net/137903-regex-geht-nicht-mehr.html)

Chefx 30. Jul 2009 21:13


Regex geht nicht mehr?
 
Hallo ich bin es mal wieder! :lol:

Delphi-Quellcode:

...
uses perlregex;

{$R *.dfm}

function verarbeitung(code:array of string;pos:array of integer):string;
var
  i:integer;
begin
for i := 0 to length(code) do
      result := result +  '|' + code[i] + ',';
end;

function regl(subj, expr: string): string;
var
  code:array of string;
  pos:array of integer;
begin
  with TPerlRegEx.Create(nil) do
    begin
      RegEx := expr;
      Subject := subj;

      if Match = false then
        begin                                                                   //
            repeat                                                              //
              code[SubExpressionCount] := SubExpressions[SubExpressionCount];   //geändert!
            until MatchAgain                                                    // aber wo is hier der fehler? 
        end;                                                                    //
        result := verarbeitung(code,pos);                                       //
    end;
end;

procedure TForm3.Button1Click(Sender: TObject);
begin
edit1.Text:=regl(edit2.Text,'<*>');           //<-------- Fehler
end;

...
So also mein Problem ist das wenn der Reguläre ausdruck korrekt ist macht er ein "Zugriffsverletzung" in der Klasse EAccessViolation :?:
Gestern abend ging es noch und wo ich dann danach noch was geändert hab (siehe oben)
war es tot!

hab schon die ganze zeit gesucht und hab das auch noch die funktion verklienert aber es geht immer noch nicht!Wo ist der Fehler(hab schon mir eine kleine Fehlerquelle erahnt)?

danke für antworten!

(ich hab garantiert was falsch gemacht :pale: )

mirage228 30. Jul 2009 21:20

Re: Regex geht nicht mehr?
 
SubExpressions dürfte von 0 bis SubExpressionCount - 1 indiziert sein.

Du gibst außerdem das erstellte TPerlRegEx nicht wieder frei, erzeugst also bei jedem Aufruf ein Speicherleck.
Weiterhin sollte man Boolean Werte nicht auf "= False" prüfen, sondern mit "not Wert".

DeddyH 30. Jul 2009 21:30

Re: Regex geht nicht mehr?
 
Ohne die Klasse zu kennen, fällt mir folgendes auf:
- das Integer-Array wird nirgends benutzt.
- die Länge des String-Arrays wird nicht gesetzt (SetLength)
- 0 bis Length kann ja nicht stimmen

Chefx 30. Jul 2009 21:37

Re: Regex geht nicht mehr?
 
wie kann ich die länge eines arrays bestimmen?
Delphi-Quellcode:
 length(code) //stimmt ja nicht

DeddyH 30. Jul 2009 21:40

Re: Regex geht nicht mehr?
 
Doch, Length() gibt Dir die Länge zurück. Aber da dynamische Arrays immer 0-indiziert sind, hat das letzte Element den Index Length - 1. Ich selbst habe mir angewöhnt, über Arrays immer mit Low() und High() zu iterieren, dann kann nichts passieren.

Chefx 30. Jul 2009 21:51

Re: Regex geht nicht mehr?
 
Delphi-Quellcode:
function verarbeitung(code:array of string;pos:array of integer):string;
var
  i:integer;
begin
for i := 0 to high(code) do
      result := result + code[i] + '|' + ',';
end;

function regl(subj, expr: string): string;
var
  code:array of string;
  pos:array of integer;
begin
  with TPerlRegEx.Create(nil) do
    begin
      RegEx := expr;
      Subject := subj;

      if Match then
        begin
            repeat
              setlength(code,SubExpressionCount-1);
              code[SubExpressionCount-1] := SubExpressions[SubExpressionCount-1];
            until MatchAgain
        end;
        result := verarbeitung(code,pos);
      end;
   TPerlRegEx.free;
end;
danke für die tipps
Die pos array will ich dann später noch einbinden.
Hab jetzt soweit alles geändert aber bei den Tperlregex.free will das nicht so gehen. warum?

DeddyH 30. Jul 2009 21:55

Re: Regex geht nicht mehr?
 
Du willst eine Klasse freigeben und keine Instanz. Also brauchst Du entweder eine Variable oder Du schreibst das in der Art
Delphi-Quellcode:
with TPerlRegEx.Create(nil) do
  try
    //Code
  finally
    Free;
  end;
[edit] Schreibfehler [/edit]

Chefx 30. Jul 2009 22:01

Re: Regex geht nicht mehr?
 
so jetzt kommt ein fehler "Fehler bei Bereichsprüfung" in der Gleichen Zeile ?
Was soll den das sein? :gruebel:
Hat das irgend was mit meinem Regulären Ausdruck zu tun?
Ich bin mir eigend lich sicher das dass so richtig ist(denken kann man viel :wink: ).

mirage228 30. Jul 2009 22:05

Re: Regex geht nicht mehr?
 
Delphi-Quellcode:
setlength(code,SubExpressionCount);
Ohne "-1". Das Array hat eine Länge von "SubExpressionCount" und der Indizierung geht von 0 an bis SubExpressionCount - 1. (Genauso wie bei SubExpressions[]).

Chefx 30. Jul 2009 22:09

Re: Regex geht nicht mehr?
 
wenn ich dort das weg mache kommt wieder der feher wie oben? :?:

DeddyH 30. Jul 2009 22:09

Re: Regex geht nicht mehr?
 
Nochmal zum Verständnis:
Delphi-Quellcode:
var Wuppdi: array of TBlubb;
...
SetLength(Wuppdi,3); //Länge auf 3 Elemente setzen
ShowMessage(IntToStr(Low(Wuppdi))); //ist bei dynamischen Arrays immer 0
ShowMessage(IntToStr(High(Wuppdi))); //ergibt 2, d.h. Index des letzten Elements
[edit] Oder mal zum Angucken:
Delphi-Quellcode:
var Bla: array of integer;
...
SetLength(Bla,3);
for i := Low(Bla) to High(Bla) do
  Bla[i] := 10;
Code:
| Index |  0 |  1 |  2 |
| Inhalt | 10 | 10 | 10 |
[/edit]

Chefx 30. Jul 2009 22:15

Re: Regex geht nicht mehr?
 
Aber da ändert sich das porblem doch nicht?
Delphi-Quellcode:
function verarbeitung(code:array of string;pos:array of integer):string;
var
  i:integer;
begin
for i := low(code) to high(code) do
      result := result + code[i] + '|' + ',';
end;

function regl(subj, expr: string): string;
var
  code:array of string;
  pos:array of integer;
begin
  with TPerlRegEx.Create(nil) do
    begin
    try
      RegEx := expr;
      Subject := subj;

      if Match then
        begin
            repeat
              setlength(code,SubExpressionCount);
              code[SubExpressionCount] := SubExpressions[SubExpressionCount];
            until MatchAgain
        end;
        result := verarbeitung(code,pos);
      finally
      free;
      end;
   end;
end;
(ist heut anscheinend nicht mein Tag!)

DeddyH 30. Jul 2009 22:21

Re: Regex geht nicht mehr?
 
Delphi-Quellcode:
setlength(code,SubExpressionCount);
code[High(code)] := SubExpressions[High(SubExpressions)];

Chefx 30. Jul 2009 22:27

Re: Regex geht nicht mehr?
 
oh stimmt ich war noch oben in der schleife :wall:

mir ist das ja schon richtig beinlich :lol: :oops: :lol: aber das funktioniert immer noch nicht so wirklich

irgend was stimmt immer noch nicht in der If-Anweisung ! :gruebel:

Chefx 30. Jul 2009 22:32

Re: Regex geht nicht mehr?
 
ach und der mekert an der zeile
Delphi-Quellcode:
 code[high(code)] := SubExpressions[High(Subexpressions)];
     //heist das nicht SubexpressionCount?

DeddyH 30. Jul 2009 22:40

Re: Regex geht nicht mehr?
 
Achso, SubExpressions ist wohl kein dynamisches Array. Dann eben so:
Delphi-Quellcode:
code[High(code)] := SubExpressions[High(code)];

//oder

code[SubExpressionCount - 1] := SubExpressions[SubExpressionCount - 1];

Chefx 30. Jul 2009 22:47

Re: Regex geht nicht mehr?
 
macht nichts!

das problem besteht immer noch ich bin mir wirklich sicher das nur hier irgendwo ein fehler ist weil immer wenn der Reg.Aus. wahr ist also wo If match ist true
dann kommt der Fehler!(Bin am verzweifel :coder2: )

Hier nochmal mein ganzer Code:
Delphi-Quellcode:
unit Unit3;

interface

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

type
  TForm3 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form3: TForm3;

implementation

uses perlregex;

{$R *.dfm}

function verarbeitung(code:array of string;pos:array of integer):string;
var
  i:integer;
begin
for i := low(code) to high(code) do
      result := result + code[i] + '|' + ',';
end;

function regl(subj, expr: string): string;
var
  code:array of string;
  pos:array of integer;
  h:integer;
begin
  with TPerlRegEx.Create(nil) do
    begin
    try
      RegEx := expr;
      Subject := subj;
//A fehlerquelle meinermeinung nach
     if Match then
        begin
            repeat
              setlength(code,SubExpressionCount);
              code[High(code)] := SubExpressions[High(code)];
            until MatchAgain;
            result := verarbeitung(code,pos);
            end;
//B Ende
      finally
      free;
      end;
   end;
end;

procedure TForm3.Button1Click(Sender: TObject);
begin
edit1.Text:=regl(edit2.Text,'<*>');
end;

procedure PatchINT3;
var
  NOP : Byte;
  NTDLL: THandle;
  BytesWritten: DWORD;
  Address: Pointer;
begin
  if Win32Platform <> VER_PLATFORM_WIN32_NT then Exit;
  NTDLL := GetModuleHandle('NTDLL.DLL');
  if NTDLL = 0 then Exit;
  Address := GetProcAddress(NTDLL, 'DbgBreakPoint');
  if Address = nil then Exit;
  try
    if Char(Address^) <> #$CC then Exit;

    NOP := $90;
    if WriteProcessMemory(GetCurrentProcess, Address, @NOP, 1, BytesWritten) and
      (BytesWritten = 1) then
      FlushInstructionCache(GetCurrentProcess, Address, 1);
  except
    //Do not panic if you see an EAccessViolation here, it is perfectly harmless!
    on EAccessViolation do ;
    else raise;
  end;
end;

initialization

// nur wenn ein Debugger vorhanden, den Patch ausführen
if DebugHook<>0 then
   PatchINT3;
end.

DeddyH 30. Jul 2009 22:54

Re: Regex geht nicht mehr?
 
Schau doch mal im Debugger, was in SubExpressions und SubExpressionCount eigentlich drinsteht. Außer, dass Du in Verarbeitung Result nicht initialisierst, sehe ich im Moment keinen Fehler (es ist aber auch schon spät am Abend).

Chefx 30. Jul 2009 23:03

Re: Regex geht nicht mehr?
 
SubExpressions[Index: integer]:string;
SubExpressionCount : integer;

Und wie meinst du das mit dem initialisieren des result!
In verarbeitung ist doch alles soweit richtig?
Delphi-Quellcode:
function verarbeitung(code:array of string;pos:array of integer):string;
var
  i:integer;
begin
for i := low(code) to high(code) do
      result := result + code[i] + '|' + ',';
end;

DeddyH 30. Jul 2009 23:05

Re: Regex geht nicht mehr?
 
Setz mal lieber als erste Zeile hinter das "begin"
Delphi-Quellcode:
Result := '';
[edit] Und ich meinte nicht die Definition, sondern zur Laufzeit nachschauen, was in den Feldern drin ist. [/edit]

Chefx 30. Jul 2009 23:19

Re: Regex geht nicht mehr?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hab mal ein Bild vom Programm gemacht
wenn man auf dem Button Oben Fehler meldung
und unten Warnung beim Erzuegen.

DeddyH 30. Jul 2009 23:22

Re: Regex geht nicht mehr?
 
Setz doch mal einen Breakpoint, steppe durch und nenne mir die Zeile und Routine, in der der Fehler auftritt.

Chefx 30. Jul 2009 23:32

Re: Regex geht nicht mehr?
 
ich hab mal getestet und bin auf diese Zeile gekommen:
Delphi-Quellcode:
54:             code[High(code)] := SubExpressions[High(code)];
55: Breack    until MatchAgain;
Sobald ich den Breackpoint dahinter setze bringt er den fehler wo ich davon ein bild gemacht hab.

DeddyH 30. Jul 2009 23:39

Re: Regex geht nicht mehr?
 
Da ich die Klasse nicht kenne: kann sich SubExpressionCount innerhalb der Schleife ändern? Wenn nicht, setz das SetLength() mal vor die Schleife.

Chefx 30. Jul 2009 23:44

Re: Regex geht nicht mehr?
 
Ne das geht nicht weil ja SubExpressions Die "suchergebnisse" hat und das ist in einem Array gespeichter und ich will Die Daten in ein anderes Array Übertragen.
Hab das trotzdem gemacht funktioniert nicht.

DeddyH 30. Jul 2009 23:44

Re: Regex geht nicht mehr?
 
Da denke ich später nochmal drüber nach, ich muss jetzt in Bett.

Chefx 30. Jul 2009 23:46

Re: Regex geht nicht mehr?
 
ich auch tschau!

ULIK 31. Jul 2009 05:08

Re: Regex geht nicht mehr?
 
Guten Morgen,

Zitat:

Zitat von Chefx

Delphi-Quellcode:

//A fehlerquelle meinermeinung nach
     if Match then
        begin
            repeat
              setlength(code,SubExpressionCount);
              code[High(code)] := SubExpressions[High(code)];
            until MatchAgain;
            result := verarbeitung(code,pos);
            end;
//B Ende

Ohne es selbst getestet zu haben: das Ganze schaut mir ziemlich suspekt aus:
  • Welchen Wert hat SubExpressionCount im Debugger!
  • was soll
    Delphi-Quellcode:
    code[High(code)] := SubExpressions[High(code)];
    eigentlich tun? Entweder ist SubExpressionsCount für jeden Treffer der RegExp neu definiert, dann überschreibst Du Dir aber ständig die Daten. Oder es wird durch das MatchAgain nicht verändert, dann schreibst Du aber immer nur Daten in den letzten Datansatz rein.
  • Was auch immer Du mit dem Pos-Array vor hast: Momentan ist es nicht initialisert!
  • Ist nun eine reine Vermutung, aber kann es sein, daß Du das hier haben willst:
    Delphi-Quellcode:
    SetLength(code, 0); //Array initialisieren
    with TPerlRegEx.Create(nil) do
    ...
    if Match then
      begin
        repeat
          nOldIndex := Length(code); // nOldIndex als integer deklarieren
          setlength(code, nOldIndex + SubExpressionCount); // Treffer um neu gefundene erweitern
          for n := 0 to SubExpressionCount - 1 do
            code[nOldIndex + n] := SubExpressions[n]; // Neue Treffer in das code Array eintragen    
        until not MatchAgain; // und weitersuchen. Abbruch, wenn kein Treffer mehr

        result := verarbeitung(code,pos); // jetzt ALLE Treffer verarbeiten
      end;
    So würde zumindest für mich der Aufbau einer Trefferliste Sinn machen.

Grüße,
Uli

Chefx 31. Jul 2009 15:12

Re: Regex geht nicht mehr?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Delphi-Quellcode:
SetLength(code, 0); //Array initialisieren
with TPerlRegEx.Create(nil) do
...
if Match then
  begin
    repeat
      nOldIndex := Length(code);
      setlength(code, nOldIndex + SubExpressionCount); // warum dann noch + SubExpressionCount
      for n := 0 to SubExpressionCount - 1 do
        code[nOldIndex + n] := SubExpressions[n]; // warum nicht nur n?     
    until not MatchAgain; // heist das nicht so viel wie nächster treffer  

    result := verarbeitung(code,pos);
  end;
Also würde ich das so Copy/Paste machen dann funktionriet es auch nicht!

Positiv: Es kommt keine Fehlernmeldung
Negativ: Es gib kein Ergebniss!

Also hier mal ein Script das ich unter C# geschrieben hab:
Code:
private void ... ;
{
   MatchCollection mc;
   Match m;
   int[] count = new int[20];
   int[] position = new int[20];

   Regex r = new Regex("{(?<contents>[^}]*)}");
   mc = r.Matches("{Text1} und {Text2}");
      //Suchergebnisse in das vorgegebene Array Speichern
   for (int i = 0; i < mc.Count; i++)
   {
      count[i] = mc[i].Length;
      position[i] = mc[i].Index;
   }
   //auslesen der Arrays
   for (int i = 0; i < mc.Count; i++)
   {
      richTextBox1.Text += "Gefundene Position:" + position[i] + "\n";
      richTextBox1.Text += "Länge vom String:" + count[i] + "\n";
   }
}
Das blöde ist dass das nicht genauso ist wie in Delphi geht! :cry:
Die MatchCollection (ist bestimmt mit in der Subexpressions eingebaut :gruebel: ) ist sehr hilfreich und der ganze aufbau halt!
Aber so funktioiert das ja nicht in delphi!

DeddyH 31. Jul 2009 16:11

Re: Regex geht nicht mehr?
 
Ich denke mal, wenn Du eine for-Schleife nehmen würdest, bekämst Du auch ein Ergebnis.

ULIK 31. Jul 2009 16:13

Re: Regex geht nicht mehr?
 
Also:

1) Deine eingestellte RegEx findet nur Texte der Bauart: ein '<', gefolgt von einem beliebigen Zeichen, gefolgt von '>', also so was wie <t> aber nicht <tt>!
2) SubexpressionCount bezieht sich auf die Anzahl der Gruppierungsklammern des regulären Ausdrucks: bei '<.>' gibt es keine, also 0. Bei '<(.+)>' ist der Count = 1!
3) Was Du suchst ist MatchedExpression und zwar zusammen mit der Option UnGreedy (behaute ich einfach mal :mrgreen: )

Schau Dir mal den Code an, der läuft bei mir fein:
Delphi-Quellcode:
function regl(subj, expr: string): string;
var
  code: array of string;
  pos: array of integer;
  regexMachine: TPerlRegEx;
begin
  SetLength(code, 0); //Array initialisieren
  regexMachine := TPerlRegEx.Create(nil);
  try
    regexMachine.RegEx := expr;
    regexMachine.Subject := subj;
    regexMachine.Options := regexMachine.Options + [preUnGreedy];
    if regexMachine.Match then
    begin
      repeat
        setlength(code, Length(code) + 1); // Treffer um neu gefundenen erweitern
        code[Length(code) - 1] := regexMachine.MatchedExpression; // Neue Treffer in das code Array eintragen
      until not regexMachine.MatchAgain; // und weitersuchen. Abbruch, wenn kein Treffer mehr

      result := verarbeitung(code,pos); // jetzt ALLE Treffer verarbeiten
    end;

  finally
    regexMachine.free;
  end;
end;
und zwar zusammen mit der RegEx '<.+>':
Delphi-Quellcode:
procedure TForm3.Button1Click(Sender: TObject);
begin
  edit1.Text := regl(edit2.Text, '<.+>'); // finde '<' gefolgt von einem oder mehreren beliebigen Zeichen gefolgt von '>'
end;
das liefert dann für den Text '<Test>er and <Test>s and <Sheep>++':

<Test>|,<Test>|,<Sheep>|,



Grüße,
Uli

Chefx 31. Jul 2009 16:15

Re: Regex geht nicht mehr?
 
statt den Repeat...Until?

DeddyH 31. Jul 2009 16:20

Re: Regex geht nicht mehr?
 
Uli hat doch bereits eine Lösung, schau Dir die mal an.

Chefx 31. Jul 2009 16:26

Re: Regex geht nicht mehr?
 
Hab ich auch gesehen war bloß zu schnell mit dem versenden! :wink:

Genau sowas hab ich gesucht (die lösung ist genial)! :thumb:
vielen dank erstmal allen die mir Geholfen haben (DeddyH,ULIK)!

Und jetzt zu der Pos.

Wie bekomme ich die Position des Gefundenen Strings Raus?
Wie in der C# gibt es ja den befehl
Code:
mc[i].Index;

ULIK 31. Jul 2009 16:29

Re: Regex geht nicht mehr?
 
Da gibt'S eine Property dafür: matchLength + matchstart glaub ich.

Uli

Chefx 31. Jul 2009 16:34

Re: Regex geht nicht mehr?
 
Delphi-Quellcode:
pos[Length(code) - 1] := regexMachine.matchedstart; // Warum ist das den Falsch
                                      ~~~~~~~~~~~~
Hab ich das falsch verstanden?

Chefx 31. Jul 2009 20:15

Re: Regex geht nicht mehr?
 
ich hab mal ein bissel probiert.
Hab das jetzt gefunden!
Die funktion für die Länge ist in Tperlregex:
Delphi-Quellcode:
regexMachine.MatchedExpressionLength;
Und die Positionbestimmen:
Delphi-Quellcode:
regexMachine.MatchedExpressionOffset;
Hier noch mal der gesamte Quelltext (fehlerfrei!):
Delphi-Quellcode:
function verarbeitung(code:array of string;pos:array of integer):string;
var
  i:integer;
begin
result:='';
for i := low(code) to high(code) do
      result := result + code[i] + '|' + inttostr(pos[i]) + ',';
end;

function regl(subj, expr: string): string;
var
  code: array of string;
  pos: array of integer;
  regexMachine: TPerlRegEx;
begin
  SetLength(code, 0); //Array initialisieren
  SetLength(pos, 0);  //
  regexMachine := TPerlRegEx.Create(nil);
  try
    regexMachine.RegEx := expr;
    regexMachine.Subject := subj;
    regexMachine.Options := regexMachine.Options + [preUnGreedy];

    if regexMachine.Match then
    begin
      repeat
        setlength(code, Length(code) + 1);// Treffer um neu gefundenen erweitern
        setlength(pos, Length(pos) + 1); //
        code[Length(code) - 1] := regexMachine.MatchedExpression;// Neue Treffer in das code Array eintragen
        pos[Length(code) - 1] := regexMachine.MatchedExpressionOffset - 1;//Position des Treffers
      until not regexMachine.MatchAgain; // und weitersuchen. Abbruch, wenn kein Treffer mehr
      result := verarbeitung(code,pos); // jetzt ALLE Treffer verarbeiten
    end;

  finally
    regexMachine.free;
  end;
end;

procedure TForm3.Button1Click(Sender: TObject);
begin
edit1.Text:=regl(edit2.Text,'<.+>');
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:26 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz