Archív Inet.sk Pôvodný autor: Michal Čižmár
27. 06. 2007 o 00:00 9977x

Programujeme v jazyku C# III. Diel 7. – Regulárne výrazy II

V dnešnom dieli Vám ukážem ako vytvoriť predkompilované regulárne výrazy a zároveň sa pozrieme ako je to potom s rýchlosťou takéhoto regEx. V druhom príklade je jednoducho vysvetlené, ako parsovať grupy údajov z textu pomocou regEx, čo je často veľmi užitočné.
Programujeme v jazyku C# III. Diel 7. – Regulárne výrazy II
[Kľúčové slová]
Compiled Regular Expression, Speed up bechmark, parsing data with RegExp
Veľa ľudí rozmýšľa, pred tým ako použije regulárny výraz vo svojej aplikácii, ako sa to odzrkadlí následne na výkone (rýchlosti) spracovania, vyhľadávania dát. Preto som spravil malý experiment, kde porovnávam :

1. Klasické overovanie dát pomocou funkcionality, ktorú nám poskytuje trieda String.
2. Pomocou klasických regulárnych výrazov
3. Použitím predkompilovaných regulárnych výrazov

>>Rýchlostné porovnanie použitia regulárnych výrazov

Nasledujúci príklad (vychádza z príkladu z predchádzajúceho dielu) má dva účely: ukázať vám, ako si prichystať predkompilovaný regulárny výraz a potom ho použijeme ne porovnanie s klasickým regEx atď.. veď čítajte ďalej.
Je dosť dlhý, ale v tomto prípade som uvážil, že je to vhodnejšie, ako robiť dva menšie príklady.

Príklad 3.7.1

using System;
using
System.Text.RegularExpressions;
using
System.Reflection;

namespace
PerformanceTest{
class
MainClass
{
    private static int IP2TEST = 400000 ;
    private static IpRegEx regExCom;
    private static Regex regExp;
    private static string pattern = @"^([01]?dd?|2[0-4]d|25[0-5])." +
        @"([01]?dd?|2[0-4]d|25[0-5]).([01]?dd?|2[0-4]d|25[0-5])." +
        @"([01]?dd?|2[0-4]d|25[0-5])$";
//------------------------------------------------
public static void Main(string[] args)
{
   
    //CreateCompiledRegEx(); Raz odkomentuj
    //Klasicke STRING vyhodnocovanie
    string [] addresses = GenerateIpAddres(IP2TEST);
    DateTime start = DateTime.Now;
    for(int i =0;i< IP2TEST; i++)
        TestIpAddr(addresses[i]);

    DateTime end = DateTime.Now;
    TimeSpan rozdiel = end - start;
    Console.WriteLine("Trvanie:" + rozdiel.TotalMilliseconds);

    //Klasicke RegEx vyhodnocovanie
    regExp = new Regex(pattern);
    start = DateTime.Now;
    for(int i =0;i< IP2TEST; i++)
        TestIpAddrRegEx(addresses[i]);

   
end = DateTime.Now;
   
rozdiel = end - start;
   
Console.WriteLine("Trvanie:" + rozdiel.TotalMilliseconds);

    //Kompilovane RegEx vyhodnocovanie
    regExCom = new IpRegEx();
    start = DateTime.Now;
    for(int i =0;i< IP2TEST; i++)
        TestIpAddrRegExCom(addresses[i]);

    end = DateTime.Now;
    rozdiel = end - start;
    Console.WriteLine("Trvanie:" + rozdiel.TotalMilliseconds);

    Console.ReadLine();
}
//------------------------------------------------
public static void CreateCompiledRegEx()
{

    //Tato cast, vygeneruje DLL so skompilovanym RegEx
    //lenze az po prvom spusteni, sa moze pridat ako referencia dll


    RegexCompilationInfo rci = new RegexCompilationInfo(
    pattern, RegexOptions.Compiled,
        "IpRegEx", "PerformanceTest", true);

    AssemblyName an = new AssemblyName();
    an.Name = "IpRegEx";

    //Skompilovanie   
    RegexCompilationInfo[] rciList = { rci };
    Regex.CompileToAssembly(rciList, an);
}
//------------------------------------------------
private static string [] GenerateIpAddres(int count)
{
    Random rnd = new Random(DateTime.Now.Second);
    string [] adresses = new string[count];
    int p1,p2,p3,p4;
    for(int i =0; i < count; i++)
    {
        p1 = rnd.Next(400);
        p2 = rnd.Next(400);
        p3 = rnd.Next(400);
        p4 = rnd.Next(400);

        adresses[i]= p1.ToString()+ "."+
        p2.ToString() + "." +
        p3.ToString() +"."+
        p4.ToString();
    }
return adresses;
}
//------------------------------------------------
public static bool TestIpAddr(string addr)
{
    char [] separator = new Char[]{'.'};
    string [] parts = addr.Split(separator);
    if (parts.Length!=4) return false;

    int onePart = 0;
    try{
    for(int i = 0; i < 4; i++)
    {
        onePart = int.Parse(parts[i]);
        if(onePart<0 || onePart>255) return false;
    }
    }
catch(Exception)
    {
    return false;
    }
return true;
}
//----------------------------------------------------
public static bool TestIpAddrRegExCom(string addr)
{
    return regExCom.IsMatch(addr);
}
//----------------------------------------------------
public static bool TestIpAddrRegEx(string addr)
{
    return regExp.IsMatch(addr);
}
//----------------------------------------------------
}
}

>>Ako sa robí predkompilovaný regulárny výraz?

Najprv si musíme uvedomiť, ako funguje vnútorný mechanizmus klasických regulárnych výrazov. Tým, že napr. pri vzniku inštancie triedy RegExp jej zadáte samotný regulárny výraz, prebehne vnútorný proces, ktorý tento vstupný string preloží do špeciálneho medzi-jazyka, ktorý je optimálny pri práci s RegEx – teda sa jednoduchšie vyhodnocuje, ale pozor nie je to MSIL.
Potom pri každom vyhodnocovaní regulárneho výrazu sa ešte prekladá tento medzi jazyk a už asi tušíte, kde sa strácajú CPU cykly.


Takže si treba dobre rozmyslieť, v akom type aplikácie sa chystáte použiť regulárny výraz. Či skôr vyžadujete prehľadnosť a jednoduchosť alebo rýchlosť.

.NET (ale napr. aj Java) nám ponúkajú ale kompromis medzi týmito dvoma voľbami vo forme predkompilovaných regEx. Všimnite si metódu CreateCompiledRegEx().
Myslím, že príklad je jasný. Podstatní je to, že takto vygeneruje samostatné assambly vo forme DLL. Takže tentoraz sa ozaj regulárny výraz rozloží do jazyka MSIL a obsahuje algoritmus len pre vyhodnocovanie jedného regulárneho výrazu.

Vhodné je na takéto regExps založiť samostatný projekt a pripojiť ho k solution. Vpríklade to vôbec nie je spravené elegantne, pretože najpr je potrebné spustit program tak, že sa zavolá len spomínaná metóda
a z toho vznikle DLL. Potom možeme jej volanie zakomentovať a vygenerovné DLL pripojiť cez references->Add->Browse a vyhldať súbor dll.

Použitie
je veľmi jednoduché, pretože ste si nachystali vlastnú triedu, ktorá ma všetky vlastnosti ako trieda Regex až na to, že vyhodnocovaný regExp je v nej na pevno zadaný. Trieda má také meno, aký ste zadali parameter pri vytváraní
RegexCompilationInfo, v našom prípade IpRegEx

>>Ako prebehlo testovanie?
Všimnite si, že v príklade je metóda [] GenerateIpAddres(int ), ktorá podľa zadanej hodnoty vygeneruje daný počet náhodných IP adries (v našom prípade 40 000).
Klasické overovanie som spravil podľa svojho uváženia a nehovorím, že by to nešlo spraviť ešte rýchlejšie.


>>Výsledky .
Graf hovorí za všetko.
Graf

Údaje sú v milisekundách.
- MODRÁ –
klasické vyhodnocovanie podľa vlastného algoritmu
- ČERVENÁ –
pomocou regulárneho výrazu
- ŽLTÁ -
použitý ten istý, ale tentoraz predkompilovaný regEx.



>>Parsovanie grúp údajov pomocnou RegExp.

Na koniec si pozrite tento príklad. Dosť to používam a možno sa to hodí aj Vám.
Pomocou syntaxe (?<group_name> pattern ) môžeme určité časti vyťažovaných dát pomenovať (dá sa k nim pristupovať aj pomocou indexov a nie mien, ale takto je to elegantnejšie).
V príklade potrebuje rozdeliť vstupný údaj na prehľadný dátum a čas. Tu by nám nepomohla ani trieda DateTime. Ak by Vám niečo nebolo v príklade jasné, napíšte prosím do diskusie, myslím si, že je dosť jedno-jednoznačný ;-) príklad.

Príklad 3.7.2

using System;
using
System.Text.RegularExpressions;
class
MainClass
{

    public
static void Main(string[] args)
    {
        //11.08.2007 8:10
        string input = "230820070825";
        string pattern =
        @"^(?<den>d{2})(?<mesiac>d{2})"+
        @"(?<rok>d{4})(?<hodina>d{2})"+
        @"(?<minuta>d{2})$";
        Regex regExp = new Regex(pattern);
        if(regExp.IsMatch(input))
        {
            MatchCollection groups = regExp.Matches(input);
           
            Console
.WriteLine("Rok:" + groups[0].Groups["rok"].Value);
            Console.WriteLine("Mesiac:" + groups[0].Groups["mesiac"].Value);
            Console.WriteLine("Den:" + groups[0].Groups["den"].Value);
            Console.WriteLine("Hodina:" + groups[0].Groups["hodina"].Value);
            Console.WriteLine("Minuta:" + groups[0].Groups["minuta"].Value);
        }
    Console.ReadLine();
    }

}




>>Čo bude nabudúce?

Nabudúce sa konečne pozrieme na utility, ktoré sú FREE a umožňujú nám tvoriť regulárne výrazy a jeden príklad zas dáme na ďalšiu možnosť použitia RegEx.
Ak máte nejaké fajn príklady na regExp, stále Vás prosím, napíšte ich do diskusie.

[Príklady z článku na stiahnutie]

porovnanie rýchlosti – cely projekt
porovnanie rýchlosti – len EXE + DLL, pre Vaše vlastné testovanie
parsovanie dátumu a času pomocou RegEx.

[Iné zdroje]

http://www.amk.ca/python/howto/regex/

http://www.ondotnet.com/pub/a/dotnet/2002/03/11/regex2.html

O rôznych typoch regEx:
http://en.wikibooks.org/wiki/Regular_Expressions/Regular_Expression_Syntaxes


[Predchádzajúce diely]

Programujeme v jazyku C# III. Diel 6. – Regulárne výrazy I
Programujeme v jazyku C# III. Diel 5. –Všetko o DataSet II.
Programujeme v jazyku C# III. Diel 4. – Všetko o DataSet I.



SEE YOU!


Michal Čižmár

Novinky a inšpirácie

Z nášho blogu

Prečítajte si novinky, inšpirácie a dôležité informácie zo sveta webhostingu a technológií.

Bezpečnostné aktualizácie PHP: Chráňte svoj web pred hrozbami Oznamy
21. 10. 2026

Bezpečnostné aktualizácie PHP: Chráňte svoj web pred hrozbami

Vývojársky tím PHP vydal dôležité bezpečnostné záplaty pre všetky oficiálne podporované verzie PHP 8. Na našich serveroch sme nezaváhali ...

Čítať viac
Gmail končí s funkciou „Odoslať ako“ pre cudzie e-mailové adresy. Čo to znamená pre vás? Oznamy
01. 10. 2026

Gmail končí s funkciou „Odoslať ako“ pre cudzie e-mailové adresy. Čo to znamená pre vás?

Google oznámil, že v januári 2027 zruší v Gmaile funkciu „Odoslať ako“ (Send as) pre e-mailové adresy od iných poskytovateľov. Ak ste si ...

Čítať viac
Večerná „prestávka“ pre server VIP033 Oznamy
25. 09. 2026

Večerná „prestávka“ pre server VIP033

Neustále pracujeme na tom, aby vaše weby bežali hladko, rýchlo a bezpečne. Technológie idú míľovými krokmi vpred a my v Inet.sk s nimi dr...

Čítať viac
Novinky na Inet.sk (09 / 2026) Novinky
09. 09. 2026

Novinky na Inet.sk (09 / 2026)

Posledné mesiace sme v Inet.sk nevenovali len stabilite serverov, ale najmä počúvaniu vašich reálnych skúseností z každodennej praxe. Výs...

Čítať viac

Podpora klientom

Máte ďalšie otázky?

Nezúfajte, pripravili sme pre Vás jednoduché odpovede na najdôležitejšie otázky, ktoré od našich klientov dostávame.

Zistiť viac

Naše výhody

Prečo si nás vybrať?

Našim klientom ponúkame až 30-dňovú záruku vrátenia peňazí.

Sme skutočný slovenský webhosting

Slovenská
firma

Nepatríme pod žiadnu nadnárodnú spoločnosť, sme malá rodinná firma.

Na nás sa môžete kedykoľvek spoľahnúť

Dlhoročné
skúsenosti

Na slovenskom trhu pôsobíme už viac ako 20 rokov, sme overená značka.

Naši prví zákazníci sú stále s nami

Spokojní
zákazníci

Naši zákazníci sú ako naša rodina, preto nám verí už viac ako 1250 klientov.

Maximálna bezpečnosť

Maximálna
bezpečnosť

Chránime Vás pred útokmi i SPAMom. U nás sú Vaše dáta v bezpečí.

Prozákaznícka podpora

Ochotná
podpora

Zakladáme si na individuálnom prístupe, preto Vám vždy radi pomôžeme.

Kvalita a dobrá cena

Férová
cena

Cena pri obnove je rovnaká ako pri objednávke. Nezdražujeme po prvom roku a bez skrytých poplatkov.

U nás sa Vám nič nestratí

Pravidelné
zálohovanie

Vaše dáta zálohujeme každý deň, dostupné sú aj zálohy z pred niekoľkých mesiacov.

Svižný Admin Panel nájdete len u nás

Prehľadný
Admin Panel

Máme rýchly a prehľadný Admin Panel, ktorý zvládne používať naozaj každý.

Správa používateľov

Správa
používateľov

Spravujte svoje projekty bez akýchkoľvek obáv s kolegami alebo externými partnermi.

Máme zľavy pre verných klientov

Vernostné
zľavy

Verní klienti u nás automaticky získavajú 15 % zľavu na každú ďalšiu objednávku.

My Vás nebudeme obmedzovať

Bez
obmedzení

Neobmedzujeme počet databáz, e-mailov, ftp a ani prenos dát.

Hosting pre WordPress

WordPress
na 1 klik

Nainštalujte si obľúbené redakčné systémy rýchlo a jednoducho.

Referencie

Spokojní zákazníci

Pozrite sa, čo o nás povedali naši klienti. Neváhajte a pridajte sa k nám ešte dnes.

Auto 100
Bystricoviny
eCall Slovakia
Filip Jančík
Frost
Merkury Broker
Mi:Su Design
Mesto Nitra
Pro Clienta
Schneider Lekáreň
Vego Marketing
Mesto Zlaté Moravce

Všetky ceny sú uvádzané bez DPH
© 2006 - 2026, Inet.sk, s. r. o., Všetky práva vyhradené

Na našej stránke používame "cookies". Vďaka nim sledujeme návštevnosť, prispôsobujeme reklamu a používateľské nastavenia, čo zlepšuje Váš zážitok z našej stránky. Súhlasíte s ich spracovaním?
Vlastné nastavenia cookies