TPerlRegEx Delphi – jak uzyskać drugie dopasowanie wyrażenia regularnego

Pytanie

TPerlRegEx, jak znajść drugie dopasowanie

Odpowiedź Sztucznej Inteligencji


Bezpośrednia odpowiedź na pytanie

  • Aby dostać drugie dopasowanie w TPerlRegEx, wywołaj najpierw Match, a następnie MatchAgain. Właściwość MatchedText po udanym MatchAgain zawiera drugie dopasowanie.
  • Kluczowe punkty:
    • Match daje pierwsze dopasowanie; MatchAgain przechodzi do kolejnego.
    • Nie wywołuj ponownie Match, jeśli chcesz iść „dalej” – zazwyczaj rozpocznie wyszukiwanie od początku.
    • Zawsze sprawdzaj wartość zwrotną (Boolean) przed odczytem MatchedText.

Szczegółowa analiza problemu

  • Główne aspekty:

    • TPerlRegEx działa stanowo: po udanym Match „pozycja wyszukiwania” zostaje ustawiona za końcem bieżącego dopasowania. MatchAgain kontynuuje od tej pozycji.
    • Przepływ dla 2. dopasowania: Match → (sukces) → MatchAgain → (sukces) → MatchedText to „drugie”.
    • Zmiana Subject, RegEx lub niektórych opcji resetuje wewnętrzną pozycję – po takich zmianach trzeba znów zacząć od Match.
  • Teoretyczne podstawy:

    • TPerlRegEx opiera się na silniku PCRE (Perl-Compatible Regular Expressions). W trybie „globalnym” iteracja po kolejnych dopasowaniach jest realizowana właśnie przez MatchAgain (odpowiednik /g w Perlu).
  • Praktyczne zastosowania:

    • Szybkie pobranie konkretnego n-tego dopasowania (np. drugiego) bez budowania listy wszystkich wyników.
    • Przetwarzanie strumieniowe: pętla Match/MatchAgain aż do wyczerpania dopasowań.

Przykłady (Delphi):

  1. Drugie dopasowanie wprost

    uses
    PerlRegEx; // lub System.RegularExpressionsCore, zależnie od projektu
    var
    R: TPerlRegEx;
    begin
    R := TPerlRegEx.Create;
    try
     R.Subject := 'abc 123 def 456 ghi 789';
     R.RegEx   := '\d+';
     if R.Match then          // pierwsze: 123
       if R.MatchAgain then   // drugie: 456
         ShowMessage('Drugie: ' + R.MatchedText)
       else
         ShowMessage('Brak drugiego dopasowania')
     else
       ShowMessage('Brak dopasowań');
    finally
     R.Free;
    end;
    end;
  2. Ogólna funkcja: n-te dopasowanie (N=2 → drugie)

    function FindNthMatch(const S, Pattern: string; N: Integer; out Value: string): Boolean;
    var
    R: TPerlRegEx;
    i: Integer;
    begin
    Result := False;
    Value := '';
    if N < 1 then Exit;
    R := TPerlRegEx.Create;
    try
     R.Subject := S;
     R.RegEx   := Pattern;
     if not R.Match then Exit;           // brak 1.
     i := 1;
     while i < N do
     begin
       if not R.MatchAgain then Exit;    // nie ma kolejnego
       Inc(i);
     end;
     Value := R.MatchedText;
     Result := True;
    finally
     R.Free;
    end;
    end;
  3. Alternatywa (nowsze API): TRegEx.Matches (kolekcja)

    uses
    System.RegularExpressions;
    var
    M: TMatchCollection;
    begin
    M := TRegEx.Matches('abc 123 def 456', '\d+');
    if M.Count >= 2 then
     ShowMessage('Drugie: ' + M.Item[1].Value);
    end;

Uwagi techniczne:

  • MatchedOffset w TPerlRegEx jest 1‑indeksowany (pozycje liczone od 1), MatchedLength to długość w znakach.
  • Jeżeli wzorzec może dopasować pusty ciąg (zero-length match), pilnuj, by przenieść pozycję ręcznie lub modyfikować wzorzec (inaczej można „utknąć” na tym samym miejscu). Bezpieczna praktyka: projektować wzorce tak, by nie dawały pustych dopasowań w iteracji globalnej.

Aktualne informacje i trendy

  • W nowoczesnych wersjach Delphi wygodniejsze w wielu przypadkach jest TRegEx (System.RegularExpressions) z kolekcją TMatchCollection oraz enumeracją dopasowań. Ułatwia to indeksowanie (np. M[1] jako „drugie”).
  • TPerlRegEx pozostaje przydatny w projektach legacy lub tam, gdzie wymagana jest pełna zgodność ze składnią PCRE i zachowaniem „perlowym”.

Wspierające wyjaśnienia i detale

  • Różnice nazw właściwości: w zależności od wersji biblioteki możesz spotkać SubExpressions[] (TPerlRegEx) lub Groups (w strukturach TRegEx/TMatch). Logika pozostaje ta sama: indeks 0 to całe dopasowanie, >0 to grupy w nawiasach.
  • Restart wyszukiwania: ponowne wywołanie Match po MatchAgain (bez zmian Subject/RegEx) zwykle zaczyna od początku. Do przechodzenia „dalej” używaj MatchAgain w pętli.

Aspekty etyczne i prawne

  • TPerlRegEx opiera się na PCRE, które jest rozpowszechniane na licencjach liberalnych (BSD‑like). W projektach komercyjnych zweryfikuj zgodność licencji użytej wersji PCRE/biblioteki.

Praktyczne wskazówki

  • Twórz osobną instancję TPerlRegEx na wątek (brak współdzielenia stanu).
  • Nie modyfikuj Subject ani RegEx między Match a MatchAgain, jeśli chcesz kontynuować iterację.
  • Jeśli chcesz jedynie „drugie” dopasowanie i nic więcej, zakończ iterację natychmiast po jego znalezieniu (oszczędność czasu).
  • Do debugowania wzorców używaj małych próbek i testów jednostkowych (edge‑case’y: brak dopasowań, jedno dopasowanie, dopasowania nakładające się, puste dopasowania).

Ewentualne zastrzeżenia lub uwagi dodatkowe

  • Szczegóły interfejsu mogą się nieznacznie różnić między jednostką PerlRegEx a System.RegularExpressionsCore (nazwy właściwości, dostępność metod pomocniczych).
  • Puste dopasowania i dopasowania nachodzące: standardowa iteracja MatchAgain nie zwraca dopasowań zachodzących na siebie; do takich przypadków trzeba użyć innej strategii (np. ręczne zwiększanie pozycji startowej i ponowne Match).

Sugestie dalszych badań

  • RAD Studio DocWiki: System.RegularExpressionsCore.TPerlRegEx (opis Match/MatchAgain, MatchedOffset/MatchedLength).
  • RAD Studio DocWiki: System.RegularExpressions.TRegEx (Matches, TMatch, NextMatch).
  • Dokumentacja PCRE (sekcje o dopasowaniach globalnych i dopasowaniach pustych).

Krótkie podsumowanie

  • Najprościej: wywołaj Match, potem MatchAgain; jeśli oba zwrócą True, MatchedText po MatchAgain to drugie dopasowanie.
  • Dla n‑tego dopasowania: pętla z kolejnymi MatchAgain aż do osiągnięcia żądanego indeksu.
  • W nowszym API rozważ TRegEx.Matches i odczyt drugiego elementu kolekcji (indeks 1).

Oceń odpowiedź:
Zastrzeżenie: Odpowiedzi udzielone przez sztuczną inteligencję (model językowy) mogą być niedokładne i wprowadzające w błąd. Elektroda nie ponosi odpowiedzialności za dokładność, rzetelność ani kompletność prezentowanych informacji. Wszystkie odpowiedzi powinny być zweryfikowane przez użytkownika.

Zadaj dodatkowe pytanie Sztucznej Inteligencji

Czekaj (2min)...