Regulární výrazy přes TRegExpr

vložil Radek Červinka 21. července 2010 00:51

V základní instalaci Delphi není podpora pro regulární výrazy (zatím), ale je třeba použít kód třetí strany.

Velmi populární je třída TRegExpr, která je volně k použití a proto dnes ukáži jak na ni.

Autorem TRegExpr je Andrey V. Sorokin, což dokazuje, že v Rusku jsou opravdu dobří programátoři (např. dříve populární RxLib - nyní součástí JVCL, FastReport atd).

Problémem je, že tato knihovna (resp. domovská stránka RegExpStudio.com) najednou zmizela z netu (komponenta se dá po chvilce hledání najít jinde) a já tipuji, že byla koupena EMBT pro začlenění do Delphi. To by nebylo poprvé, viz komponenta TPNGImage (Gustavo Daud), která je nyní součástí VCL. Ale třeba nemám pravdu, každopádně zde je TRegExpr (originální), ve verzi i pro unicode Delphi.

Update:V komentáři doporučuje pepak jeho verzi s opravou drobných chyb a hlavně helpem - TRegExpr a help.

Třída umožňuje i kompilaci výrazů do interního p-code pro urychlení provádění.

Následující kód je konzolová aplikace obsahující dva příklady:

  • první příklad ze zadaného html kódu odstraní tagy a výsledek zobrazí (dokud nezadáte prázdný text)
  • druhý příklad po zadání url (ve tvaru http://adresa) načte HTML a vypíše obsah Title

Prakticky ve všech našich projektech používám kód Synapse, teď pro jednoduchost použiji Indy, jelikož jsou součástí Delphi a tak demo půjde kompilovat bez větších problémů.

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils, RegExpr, IdHTTP;
var
  oRegExpr: TRegExpr;
  s: string;
  IdHTTP: TIdHTTP;

begin
  try
    writeln('Priklad 1: Zadejte html:');
    oRegExpr := TRegExpr.Create;
    try
      // nahradi tagy za ''
      oRegExpr.Expression := '<(.|\n)+?>';
      while true do
      begin
        ReadLn(s);
        if s = '' then
          break;
        oRegExpr.Exec(s);
        writeln('Result= '+oRegExpr.Replace(s, '', true));
      end;
    finally
      FreeAndNil(oRegExpr);
    end;

    writeln('Priklad 2:Zadejte URL:');
    oRegExpr := TRegExpr.Create;
    IdHTTP := TIdHTTP.Create(nil);
    try
      oRegExpr.Expression := '<title>(.*?)</title>';
//      s := 'http://delphi.cz';
      ReadLn(s);
      if s= '' then
        Exit;
      s := IdHTTP.Get(s);
      oRegExpr.Exec(s);
      writeln('Title:'+ oRegExpr.Match[1]);
    finally
      FreeAndNil(oRegExpr);
      FreeAndNil(IdHTTP);
    end;


  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Tagy: , ,

Komponenty

Komentáře

21.7.2010 7:06:10 #

pepak

Knihovnu TRegExpr jsem ve svých starších projektech také používal, dnes už bych ji ale nedoporučil:

- je velmi pomalá
- obsahuje chyby ve vyhodnocování výrazů (bohužel si teď nevzpomenu, které to byly; nebylo to nic extra vážného, ale dost na to, abych na to narazil; porovnáním zdrojáku zjišťuju například chybné escapování znaků v metodě Substitute)
- obsahuje jen velmi malou podmnožinu toho, co umí komponenty postavené nad knihovnou PCRE (já např. velmi rád používám pojmenované podvýrazy nebo specifikátor pro nezapočítání závorky do podvýrazu)

Pokud už někdo chce TRegExpr používat, stáhněte si tuhle verzi (prosím admina Delphi.cz, aby ji hodil na svůj web, abych ji mohl z dočasného úložiště smazat):
http://tmp.pepak.net/regexpr.zip
Opravil jsem v ní pár drobných chybek a hlavně je v ní původní .hlp soubor s nápovědou.

pepak

21.7.2010 10:20:12 #

radekc

Moc díky,
přidal jsem možnost stáhnout tvoji verzi do článku.
Nevýhodou PCRE je právě ta DLL, ale chápu že někdo kdo používá regulární výrazy intenzivně to překousne.

Ovšem pro občasné použití mi přijde uvedená třída dostačující.

Mimochodem jaké zapouzdření PCRE by jsi doporučil, když už jsi to nakousl?

radekc

21.7.2010 10:30:24 #

pepak

Vzhledem k tomu, že stále ještě používám zejména Delphi 5, tak DPCRE 6.7 ( http://www.renatomancuso.com/software/dpcre/dpcre.htm ), která jde na kompatibilitu snadno upravit (nicméně doporučil bych spíš stáhnout zdroják mého YouTube Downloader [ http://www.pepak.net/download/youtube-downloader/ ], kde je v adresáři Source\Lib\DPCRE67 mírně upravená verze, která podporuje Delphi 5 i Delphi 2009+). V tom YTD se také dají najít spousty příkladů, jak tu komponentu používat.

Pro majitele novějších Delphi může být lepší TPerlRegExp ( http://www.regular-expressions.info/delphi.html ), která je postavená na novějším PCRE, je často aktualizovaná, přímo podporuje Delphi 2009+ a má blíž ke klasickým komponentám (DPCRE67 používá jakousi podivuhodnou kombinaci interfaců a tříd, u které se nemůžu zbavit podezření, že to zůstává po "uvolnění" v paměti - to mi připomíná, že mám do další verze YTD udělat další malou úpravu DPCRE, abych ji mohl spolehlivě uvolňovat).

pepak

21.7.2010 20:30:18 #

pepak

Zkoušel jsem trochu ten TPerlRegExp. Dá se rozchodit i pod Delphi 5, stačí vymazat sérii IFDEFů na začátku a nahradit je zvoleným DEFINEm. Za jednoznačnou výhodu proti DPCRE považuju to, že jde zkompilovat staticky, aby nepotřeboval DLL, a dál to, že to je klasická komponenta, takže není problém s uvolňováním paměti. Uživatele Delphi 2009+ potěší i naprosto transparentní podpora unicode. Naopak se mi moc nelíbil způsob používání, například práce s pojmenovanými podvýrazy je rozhodně méně pohodlná než u DPCRE. Pokud někdo potřebuje velký výkon, tak nevýhodou DPCRE je i to, že k jednomu regexpu jde mít v jednu chvíli udělané jen jedno hledání - nejde z už jednou připraveného regexpu připravit druhou instanci.

To jsou ovšem zatím jen poznatky ze studia zdrojáku, ke skutečnému kódu se dostanu až později...

pepak

22.7.2010 19:11:29 #

pepak

Takže ten TPerlRegEx: Pracuje se s ním celkem dobře, pokud člověk netrvá na specialitách toho typu, že s jedním zkompilovaným výrazem bude chtít současně prohledávat víc řetězců. Zase to ale nemá problémy s uvolňováním paměti. Rozhraní komponenty mi místy přijde poměrně nepohodlné (práce s pojmenovanými podvýrazy), ale jsou to opravdu jen ojedinělé případy. Horší je, že jsou použité trochu zvláštní defaulty (např. jen 99 podvýrazů ve standardní distribuci; naštěstí je to řešené konstantou, takže to jde snadno změnit). Jediný vyslovený problém je to, že komponenta má nějak divně nastavenou knihovnu PCRE, takže to vytváří i podvýrazy, které by nemělo (resp. které se v DPCRE nevytvářely):

(?:[a-z]*(?P<cislo>[0-9]+)[a-z]*)?

V tomto výrazu TPerlRegEx naplní (označí jako existující) pojmenovaný podvýraz "cislo" i v případě, že vnejší závorka není splněna.

V dnešní verzi YouTube Downloaderu už je to zamontované a jsou tam opět provedené drobné opravy (kompatibilita s Delphi 5, navýšen počet podvýrazů).

pepak

Komentování ukončeno

Naše nabídka

MVP
Ing. Radek Červinka - Embarcadero MVP
profil na linkedin, Twitter:@delphicz

Nabízím placené poradenství a konzultace v oblasti programování a vývoje SW.
Dále nabízíme i vývoj speciálního software na zakázku.

Neváhejte nás kontaktovat (i ohledně reklamy).

love Delphi

O Delphi.cz

Delphi je moderní RAD nástroj podporující tvorbu nativních aplikací pro platformu Win32, Win64, Mac OSX, Linux a na iPhone a Android.

Delphi.cz je nezávislý portál pro uživatele Delphi. Portál není koncipován pro úplné začátečníky, i když i ti se zde nebudou nudit, ale spíše na programátory, kteří již něco znají a chtějí své znalosti dále rozvíjet a sledovat novinky.

Poslední komentáře

Comment RSS

Dle měsíců