Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   REGEX mit TMatchCollection (https://www.delphipraxis.net/215546-regex-mit-tmatchcollection.html)

wschrabi 25. Jul 2024 10:24

REGEX mit TMatchCollection
 
Liebe Leute,
REGEX macht Probleme.
Hier mein CODE:

Delphi-Quellcode:
function Tform1.getGefkl(text: string): string;
var
  pattern,mainToken,subTokens: string;
  matches: TMatchCollection;
  match: TMatch;
begin

 text := 'ABSCHNITT 14: Angaben zum Transport'#13#10 +
          '14.1 UN-Nummer'#13#10 +
          'ADR/RID: 2735 IMDG: 2735 IATA: 2735'#13#10 +
          '14.2 Ordnungsgemäße UN-Versandbezeichnung'#13#10 +
          'ADR/RID: AMINE, FLÜSSIG, ÄTZEND, N.A.G. (3-Aminopropyltriethoxysilan) IMDG: AMINES, LIQUID, CORROSIVE, N.O.S. (Triethoxy(3-aminopropyl)silane) IATA: Amines, liquid, corrosive, n.o.s. (Triethoxy(3-aminopropyl)silane)'#13#10 +
          '14.3 Transportgefahrenklassen ADR/RID: 6.1 (3, 8)'#13#10 +
          '14.4 Verpackungsgruppe ADR/RID: II'#13#10 +
          '14.5 Umweltgefahren ADR/RID: nein'#13#10 +
          'IMDG: 8'#13#10 +
          'IMDG: II'#13#10 +
          'IMDG Meeresschadstoff: nein'#13#10 +
          'IATA: 8'#13#10 +
          'IATA: II';
         
  pattern := '(1|2|3|4\.1|4\.2|4\.3|5\.1|5\.2|6\.1|6\.2|7|8|9)(?:\s*\((1|2|3|4\.1|4\.2|4\.3|5\.1|5\.2|6\.1|6\.2|7|8|9(?:,\s*(1|2|3|4\.1|4\.2|4\.3|5\.1|5\.2|6\.1|6\.2|7|8|9))*)\))?';

 

  matches := TRegEx.Matches(text, pattern);

  if matches.Count > 0 then
  begin
    if match.Groups.Count>1 then
      begin
       for match in matches do
       begin
         mainToken := match.Groups[1].Value;
         subTokens := match.Groups[2].Value;
         if subTokens <> '' then
           Result:= mainToken+' ('+ subTokens+ ')'
         else
           Result:= mainToken;
       end;
      end;
  end
  else
  begin
    Result:='';
  end;
  Show_UpDate_LOG(clBLue,mymodeRUN,Format('Match:(%s ):COUNT:%d',[Result,matches.Count]));
 
 
end;
Die Counts der Gruppen sind immer 0!
AUch Sagt mir Perplexity.ai dass.

Ja, es gibt bekannte Probleme und Herausforderungen bei der Verwendung von regulären Ausdrücken und der Gruppenzählung in Delphi. Hier sind einige relevante Punkte, die in den Suchergebnissen und der allgemeinen Erfahrung mit Delphi hervorgehoben werden:

1. **Performance-Probleme mit regulären Ausdrücken**: Delphi XE4 bis Delphi 10.2 verwenden die UTF-8-Version von PCRE, obwohl PCRE bereits native UTF-16-Unterstützung hatte. Dies führt zu ständigen Konvertierungen zwischen UTF-16 und UTF-8, was die Leistung der regulären Ausdrücke insbesondere bei langen Zeichenfolgen erheblich beeinträchtigen kann[3].

2. **Probleme mit der Gruppenzählung**: Es gibt Berichte über Probleme mit der Gruppenzählung in Delphi, insbesondere wenn es um die Verwendung von regulären Ausdrücken geht. Dies kann auf die Art und Weise zurückzuführen sein, wie Delphi die PCRE-Bibliothek implementiert und verwendet[3].

3. **Komponenten- und Kontrollzählung**: Ein verwandtes Problem, das in Delphi häufig auftritt, ist die Verwirrung zwischen `ComponentCount` und `ControlCount`. Dies kann zu Missverständnissen führen, wenn versucht wird, die Anzahl der Komponenten oder Steuerelemente in einem Container zu zählen[2].

Um diese Probleme zu umgehen, können folgende Ansätze hilfreich sein:

- **Verwendung von `TRegEx`**: Stellen Sie sicher, dass Sie die `TRegEx`-Klasse korrekt verwenden und die Gruppen richtig referenzieren. Prüfen Sie, ob die Gruppen tatsächlich vorhanden sind, bevor Sie auf sie zugreifen.
- **Prüfen der PCRE-Version**: Überprüfen Sie, welche Version von PCRE Ihre Delphi-Version verwendet und ob es möglich ist, auf eine neuere Version zu aktualisieren, die native UTF-16-Unterstützung bietet.
- **Debugging und Tests**: Führen Sie umfangreiche Tests durch, um sicherzustellen, dass die regulären Ausdrücke wie erwartet funktionieren, und verwenden Sie Debugging-Tools, um Probleme zu identifizieren.

Hier ist ein Beispiel, wie Sie sicherstellen können, dass die Gruppen korrekt gezählt und referenziert werden:

```

Delphi-Quellcode:
uses
  System.RegularExpressions, System.SysUtils;

var
  text: string;
  pattern: string;
  matches: TMatchCollection;
  match: TMatch;
  mainToken, subTokens: string;
begin
  text := 'ABSCHNITT 14: Angaben zum Transport'#13#10 +
          '14.1 UN-Nummer'#13#10 +
          'ADR/RID: 2735 IMDG: 2735 IATA: 2735'#13#10 +
          '14.2 Ordnungsgemäße UN-Versandbezeichnung'#13#10 +
          'ADR/RID: AMINE, FLÜSSIG, ÄTZEND, N.A.G. (3-Aminopropyltriethoxysilan) IMDG: AMINES, LIQUID, CORROSIVE, N.O.S. (Triethoxy(3-aminopropyl)silane) IATA: Amines, liquid, corrosive, n.o.s. (Triethoxy(3-aminopropyl)silane)'#13#10 +
          '14.3 Transportgefahrenklassen ADR/RID: 6.1 (3, 8)'#13#10 +
          '14.4 Verpackungsgruppe ADR/RID: II'#13#10 +
          '14.5 Umweltgefahren ADR/RID: nein'#13#10 +
          'IMDG: 8'#13#10 +
          'IMDG: II'#13#10 +
          'IMDG Meeresschadstoff: nein'#13#10 +
          'IATA: 8'#13#10 +
          'IATA: II';

  pattern := '(1|2|3|4\.1|4\.2|4\.3|5\.1|5\.2|6\.1|6\.2|7|8|9)(?:\s*\((1|2|3|4\.1|4\.2|4\.3|5\.1|5\.2|6\.1|6\.2|7|8|9(?:,\s*(1|2|3|4\.1|4\.2|4\.3|5\.1|5\.2|6\.1|6\.2|7|8|9))*)\))?';

  matches := TRegEx.Matches(text, pattern);

  if matches.Count > 0 then
  begin
    for match in matches do
    begin
      mainToken := match.Groups[1].Value;
      if match.Groups.Count > 2 then
        subTokens := match.Groups[2].Value
      else
        subTokens := '';
       
      if subTokens <> '' then
        WriteLn('Gefundener Ausdruck: ', mainToken, ' (', subTokens, ')')
      else
        WriteLn('Gefundener Ausdruck: ', mainToken, ' ()');
    end;
  end
  else
  begin
    WriteLn('Gefundener Ausdruck: ');
  end;
end.
Dieser Code stellt sicher, dass die Gruppen korrekt erfasst und ausgegeben werden, und zeigt leere Strings an, wenn keine Gruppen vorhanden sind.

Citations:
[1] https://www.delphipraxis.net/213258-...-debuggen.html
[2] https://stackoverflow.com/questions/...pbox-returns-0
[3] https://www.regular-expressions.info/delphi.html
[4] https://en.delphipraxis.net/topic/85...erent-columns/

Kann mir jemand sagen wie ich das Problem löse? Ich habe 10.1 BERLIN RAD
DANKE

shebang 25. Jul 2024 11:27

AW: REGEX mit TMatchCollection
 
Zitat:

Zitat von wschrabi (Beitrag 1539200)
Delphi-Quellcode:
if matches.Count > 0 then
  begin
    if match.Groups.Count>1 then
Die Counts der Gruppen sind immer 0!

Das liegt daran, dass du hier auf match statt auf matches zugreifst.

peterbelow 25. Jul 2024 11:35

AW: REGEX mit TMatchCollection
 
Es würde helfen, wenn Du uns auch sagen würdest, was Du in den einzelnen Gruppen als Resultat erwartest. Eine komplexe regex korrekt zu formulieren ist schwierig und sehr fehleranfällig. Ich würde den Text mittels einer TStringlist erstmal in Zeilen zerlegen und dann die Zeilen nacheinander analysieren.

wschrabi 25. Jul 2024 12:42

AW: REGEX mit TMatchCollection
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von shebang (Beitrag 1539208)
Zitat:

Zitat von wschrabi (Beitrag 1539200)
Delphi-Quellcode:
if matches.Count > 0 then
  begin
    if match.Groups.Count>1 then
Die Counts der Gruppen sind immer 0!

Das liegt daran, dass du hier auf match statt auf matches zugreifst.

Nein, wenn ich matches.Groups.Count mache kommt ein Compiler Fehler. (siehe BILD)
ABer etwas stimmt, ich muss die IF in die loop reintun.

EIN TREFFER wäre lt. der REGEX: 6.1 (3, 8)
im TEXT die Zeile 14.3
Die Regex müßte aber passen, doch wieso ist Groups immer 0. Was hat es mit den Bug - wie berichtet auf sich?
Besten DANK

shebang 25. Jul 2024 13:41

AW: REGEX mit TMatchCollection
 
Du kannst das Ganze etwas vereinfachen, deine for-Schleife fängt den Fall, dass es keine Matches gibt schon ab:
Delphi-Quellcode:
for match in matches do begin
  if match.Groups.Count < 3 then Continue;

  mainToken := match.Groups[1].Value;
  subTokens := match.Groups[2].Value;
  if subTokens <> '' then
    Result:= mainToken+' ('+ subTokens+ ')'
  else
    Result:= mainToken;
end;
Deine RegEx enthält aber nur eine Capturing Group und eine Non-capturing Group, es wird also nie mehr als 2 Groups geben können.
Beschreibe doch bitte mal, was deine RegEx eigentlich erreichen soll.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:18 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