TPerlRegEx Delphi – wyciąganie tekstu od słowa ala do bela, leniwe dopasowanie
Pytanie
TPerlRegEx Delphi, wyszukiwanie od słowa ala do słowa bela reszta pomijana
Odpowiedź Sztucznej Inteligencji
Bezpośrednia odpowiedź na pytanie
- Najprościej: użyj wzorca z „leniwyą” kropką i granicami słów: \bala\b([\s\S]*?)\bbela\b
- W TPerlRegEx:
- RegEx := '\bala\b([\s\S]*?)\bbela\b';
- Subject := Tekst;
- Options: [preCaseLess] (opcjonalnie), [preSingleLine] gdy chcesz użyć kropki „.” zamiast [\s\S]
- Wynik między słowami masz w Groups[1]; całe „od ala do bela” w MatchedText.
Szczegółowa analiza problemu
- Cel: wydobyć (i ewentualnie jedynie zostawić) fragment zaczynający się na słowo „ala” i kończący na słowo „bela”, pomijając resztę.
- Teoria:
- „Leniwość” (quantifier ?): .? lub [\s\S]*? zatrzymuje się na najbliższym kolejnym dopasowaniu „bela”, zamiast pożerać aż do ostatniego „bela”.
- Granice słowa \b: gwarantują, że nie trafisz w „kalafior” (z „ala”) ani „tabela” (z „bela”).
- Nowe linie: „.” domyślnie nie obejmuje CR/LF; dwie równoważne drogi:
- Wzorzec z [\s\S]*? (działa bez zmiany opcji).
- Albo „.” + preSingleLine (DOTALL).
- Praktyka (TPerlRegEx – System.RegularExpressionsCore/RegularExpressionsCore, zależnie od wersji Delphi):
- Pojedyncze dopasowanie i pobranie środka:
uses System.RegularExpressionsCore;
var R: TPerlRegEx;
begin
R := TPerlRegEx.Create;
try
R.RegEx := '\bala\b([\s\S]*?)\bbela\b';
R.Subject := InputText;
// R.Options := [preSingleLine]; // gdy używasz „ala.*?bela”
if R.Match then
ShowMessage('Między: ' + R.Groups[1]) // tylko wnętrze
else
ShowMessage('Brak dopasowania');
finally
R.Free;
end;
end;
- Wszystkie wystąpienia (iteracja):
if R.Match then
repeat
Memo1.Lines.Add(R.Groups[1]); // wnętrze
until not R.MatchAgain;
- Zatrzymanie słów w wyniku (włącznie z „ala” i „bela”): użyj grupowania całego fragmentu:
- Wzorzec: (\bala\b[\s\S]*?\bbela\b)
- Wtedy R.Groups[1] zawiera cały fragment wraz z „ala” i „bela”.
- „Zachłanne” dopasowanie (od pierwszego „ala” do ostatniego „bela”): \bala\b[\s\S]*\bbela\b (bez „?”). Zwykle niepożądane tutaj.
Aktualne informacje i trendy
- Nowe Delphi (XE+ … 12.x) dostarcza dwa API:
- TPerlRegEx (System.RegularExpressionsCore): PCRE-owy silnik, klasyczne właściwości (Subject, RegEx, Options, Groups[], MatchAgain).
- TRegEx (System.RegularExpressions): record-API; analogiczne wzorce, opcje roSingleLine/roIgnoreCase; jeśli nie potrzebujesz TPerlRegEx, TRegEx bywa prostszy w użyciu.
- Rekomendacja projektowa: jeśli nie masz zależności historycznych od TPerlRegEx, rozważ TRegEx.Matches dla czytelności i prostego zarządzania pamięcią.
Wspierające wyjaśnienia i detale
- Warianty wzorca:
- Tylko całe słowa i ignorowanie wielkości: (?i)\bala\b([\s\S]*?)\bbela\b lub Options: [preCaseLess].
- Bez nowych linii: \bala\b(.*?)\bbela\b i Options bez preSingleLine.
- Dodatkowe białe znaki przy brzegach: \bala\b\s([\s\S]?)\s*\bbela\b
- Różnice „.” vs [\s\S]:
- „.” + preSingleLine jest czytelne.
- [\s\S] jest niezależne od opcji (przenośne między silnikami).
- Wydajność:
- Leniwe .*? przy bardzo długich fragmentach bez „bela” przeskanuje koniec tekstu – to normalne.
- Możesz zastosować „temperowaną kropkę” dla redukcji backtrackingu: \bala\b(?:(?!\bbela\b)[\s\S])*?\bbela\b
Aspekty etyczne i prawne
- Korzystając z bibliotek zewnętrznych (gdybyś użył alternatyw typu TRegExpr), sprawdź licencję. TPerlRegEx/TRegEx dostarczane z Delphi są bezpieczne licencyjnie w ramach licencji RAD Studio.
Praktyczne wskazówki
- Jeśli chcesz „zostawić tylko fragment, resztę wyciąć”, najprościej:
- if R.Match then Output := R.MatchedText else Output := '';
- W TRegEx (alternatywa):
uses System.RegularExpressions;
var M := TRegEx.Match(InputText, '\bala\b([\s\S]*?)\bbela\b',
[roIgnoreCase, roSingleLine]);
if M.Success then
Output := M.Value; // cały fragment od ala do bela
- Testuj dane skrajne:
- Brak „bela”, wielokrotne „ala/bela”, nowe linie, „Ala”/„BELA”, wystąpienia w środku innych słów.
Ewentualne zastrzeżenia lub uwagi dodatkowe
- \b i Unicode: w typowych ustawieniach działa poprawnie, ale dla tekstów silnie diakrytyzowanych sprawdź, czy granice słów odpowiadają Twoim oczekiwaniom (silnik PCRE z ustawieniami Delphi zwykle to obsługuje prawidłowo).
- Ogromne pliki: rozważ strumieniowe przetwarzanie lub bardziej specyficzne wzorce, by skrócić skanowanie.
Sugestie dalszych badań
- Dokumentacja System.RegularExpressionsCore.TPerlRegEx i System.RegularExpressions.TRegEx (RAD Studio DocWiki).
- Poradniki PCRE nt. leniwych/zachłannych kwantyfikatorów i granic słów.
- Narzędzia do interaktywnego testowania regex (np. RegexBuddy) z profilem „Delphi/PCRE”.
Krótkie podsumowanie
- Użyj: \bala\b([\s\S]*?)\bbela\b z TPerlRegEx.
- Groups[1] to „między ala i bela”, MatchedText to cały fragment wraz z granicznymi słowami.
- Dla nowych linii: [\s\S]*? lub preSingleLine; dla „Ala”/„BELA”: preCaseLess.
- Iterację po wielu dopasowaniach załatwia MatchAgain. Jeśli podasz konkretny przykład wejścia/oczekiwań, doprecyzuję wzorzec i kod.
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