Regulární výrazy v .NET

Tomáš Jecha, MVP, MCSD       12.01.2009       C#, VB.NET, Regulární výrazy, .NET       21334 zobrazení

Chcete vědět k čemu se dají prakticky použít? Jak je psát a jak snadno implementovat v .NET? Kompletního průvodce najdete v tomto článku.

Regulárním výrazů se někteří výojáři vyhýbají jako čert kříži. Přitom se jedná se jen pokročilejší způsob práce s řetězci pomocí textových šablon nazývaných právě regulární výrazy (dále už jen RV). Druhů RV existuje hned několik, já budu hovořit o regulárních výrazech odvozených z jazyka Perl, konkrétně o jejich implementaci v .NET Frameworku. Bude nás zajímat jmenný prostor System.Text.RegularExpressions.

Regulární výraz  Teoretický postup využití

Pro programátora jejich využití znamená v první řadě výraz navrhnout – to si popíšeme dále. V druhém kroku vezmeme vstupní text, který chce zpracovat a RV na něj aplikuje. Výsledkem je sada shod. Pokud v sadě není shoda žádná, výraz nesouhlasí se vstupním textem. Naopak při jedné shodě RV souhlasí na jednom místě vstupního textu a při několikanásobné shodě i na více místech.

V .NET Frameworku nalezneme i řadu dalších funkcí (Raplace, IsMatch atp.) – ty všechny ale jen usnadňují práci s procesem, který jsem popsat v předchozím odstavci.

Nejlépe poslouží jednoduchý příklad. Mějme text, v němž hledáme slovo “ale”. Navrhneme RV pro hledání slova “ale” a aplikujeme ho na vstupní text. Výsledek zpracování bude obsahovat přesný počet shod jako slov “ale” ve vstupním textu. Zároveň získáme přesné pozice, na kterých se hledaná slova nachází.

Psaní regulárních výrazů

Regulární výrazy vyhlížejí děsivě, ale při znalosti několika elementárních principů a speciálních znaků se stávají jednoduchým a přehledným nástrojem. Navíc jestli jste odpůrci nepřirozeného školního cpaní informací do hlavy, používejte praktický přehled z této kapitoly tak dlouho, než se vše naučíte nazpaměť běžným používáním. Nebude to trvat dlouho, slibuji.

K prvním pár elementům zkusim navíc napsat jejich ekvivalenty mezi funkcemi .NETu pro práci s řetězci, aby bylo patrné k čemu jdou používat. Proti funkcím mají však RV výhodu možnosti libovolné kombinace jednotlivých elementů, to ale ukážu až v pokročilejších funkcích, teď je na čase pochopit elementy základní.

Element – speciální znaky a přímý text

Při psaní RV budeme chtít často zapsat obyčejný text, jehož výskyt budeme ve vstupním řetězci hledat. To jde udělat přímo, jen si musíme dát pozor na tyto speciální znaky:

. $ ^ { [ ( | ) ] } * + ? \ 

Například při hledání textu obsahující frázi “Ahoj (text v závorce).” musíme v RV zapsat: “Ahoj \(text v závorce\)\.” – každý speciální znak je potřeba nahradit za únikovou sekvenci začínající \.

Pokud RV obsahuje jen přímý text, nalezneme shodu v každém řetězci, co ho obsahuje. Třeba výraz “ahoj” najde přesně tolik shod, kolik je slov “ahoj” ve zpracovávaném řetězci. Tím můžeme nahradit funkci Contains – zjišťuje přítomnost kusu textu v řetězci.

Elementy začátku a konce textu (znaky ^ a $)

V minulém odstavci bylo řečeno, že přímý text může být umísťen kdekoliv v hledaném řetězci. Pomocí znaku ^ můžeme určit ve výrazu začátek a pomocí $ zase konec.

Například výraz “^Ahoj” nalezne 1 shodu, pokud zpracovávaný řetězec začíná slovem Ahoj. Jakýkoliv výskyt slova Ahoj jinde než na začátku neodpovídá výrazu.

Stejným způsobem můžeme používat i znak $ reprezentující konec textu. Třeba “\.$” najde 1 shodu s textem končícím znakem tečky (všimněte si zpětného lomítka, tečka je speciální znak vyžadující únikovou sekvenci).

Znak konce i začátku můžeme zapsat do jednoho RV. Ukázkou může být “^Ahoj$”. Takový RV najde shodu jen s řetězcem “Ahoj”, nic nesmí být před ním, ani za ním, protože jsme upřesnili začátek i konec.

Těmito speciálními znaky můžeme nahradit textové funkce StartsWith, EndsWith když umístíme na začátek přímého textu ^, kontroluje, zda řetězec přímým textem začíná (StartsWith) a při umístění $ na konec, zase, zda přímým textem končí (EndsWith).

Element alternativy (znak |)

Zatím umíme hledat začátek a konec a výskyty přímého textu. To moc možností zatím nedává a určitě by to nikoho nepřesvědčilo RV používat. Teď se ale podíváme na první zajímavější element v podobě znaku |. Určuje možnosti, něco jako v programování operátor OR (nebo).

Výrazu “Katka|Marek” bude nalezeny shody u všech textů obsahující slova Katka nebo slova Marek. Pokud jich bude v textu více, najde se i více shod. Navíc možností můžeme uvést klidně i víc, třeba “Katka|Marek|Andrea”.

Už zde můžeme elementy různě míchat, například RV “^Nazdar|Ahoj$” bude platný v případě, že řetězec buď končí slovem Ahoj nebo začíná Nazdar.

Elementy skupiny (znak jednoduchých závorek)

V předchozí kapitolce jsme probírali znak |. Nejen pro jeho komplexnější využití je potřeba seskupování. Nejlépe půjde účel skupin ukázat na příkladu:

Chceme rozpoznávat dvě slova - Lucka a Lucko. To jde sice udělat výrazem “Lucka|Lucko”, ale s použitím skupiny máme možnost alterovat jen jeden znak: “Luck(a|o)”. Určitě vidíte podobnost spoužíváním závorek u logických výrazů v programování, je to v zásadě hodně podobné:

If Pismeno1 = “L” And Pismeno2 = “u” And Pismeno3 = “c” And Pismeno4=”k” And (Pismeno5 = “a” Or Pismeno5 = “o”)

Element libovolného znaku (znak . )

Zatím jsme pracovali jen s přímým textem. Naštěstí v RV můžeme používat i obecné zástupné znaky. Nejzákladnější je znak tečky, reprezentující jeden libovolný znak. Nemyslím, že je na tom moc co vysvětlovat, výraz “Tom.š” odpovídá všem řetězcům obsahujícím slovo “Tom(libovolný znak)š”. Tedy namátkou slova Tomáš, Tom3š, Tom-š, Tomzš atp.

Elementy počtu (znaky složených závorek)

Za každý znak, skupinu, či zástupný symbol můžeme zapsat kolikrát se může opakovat minimálně a kolikrát maximálně. Implicitně je to vždy jeden znak, proto nemusíme počty uvádět za každým písmenem, které se má objevit jen jednou.

Formát zápisu je následující “{minum,maximum}”, popřípadě, pokud je počet stálý, tak “{počet}”. Ve výrazu se pak může výskytovat třeba takto: “Aho{5}j” odpovídá řetězci s textem “Ahoooooj”, protože jsme určili, že počet písmene “o” bude muset být 5. Rozsah dává možností více, třeba: “Aho{1,3}j” odpovídají slova “Ahoj”, “Ahooj”, “Ahoooj”.

V případě, že neuvedeme horní mez stejně jako zde: “{minimum,}”, bude maximální počet nekonečný. Nazpomeňte ale na čárku, jinak se bude brát počet jako pevný.

Pokud aplikujeme určení počtu písmen na skupinu, musí se opakovat celá skupina. Třeba “(Ahoj){2}” odpovídá “AhojAhoj”. Je samozřejmé, že můžeme kombinovat i další elementy. Například “(Ahoj|Nazdar){5}$” najde shodu v textu, který končí 5ti slovy buď Ahoj nebo Nazdar za sebou.

Další elementy počtů (znaky * + ? )

Pro usnadnění zápisu jsou tři nejpoužívanější elementy počtů zkráceny do nasledujících znaků. Jejich použití je však identické jako u verze v předchozí kapitole, zapisují se za znak, skupinu, či zástupný symbol:

  • Znak * – znamená “{0,}” – 0 nebo více výskytů
  • Znak + – znamená “{1,}” – 1 a více výskytů
  • Znak ? – znamená “{0,1}” – žádný nebo jeden výskyt

Element výčtu znaků (znaky hranatých závorek)

Jako jeden znak dokážeme teď uvést konkrétní písmeno nebo libovolný znak (zástupný symbol tečky). Bylo by fajn umět vytvořit výčet možných znaků.

Dá se to zařídit pomocí konstrukce z hranatých závorek ve formátu “[výčet znaků]”. Do nich uvedeme výčet (popřípadě rozsah) povolených znaků. Například výraz ”[abc]{2}” vyhledá výskyty kombinací písmen ve výčtu o délce 2 znaků, tedy: aa, ab, ac, ba, bb, bc, ca, cb, cc.

Do hranatých závorek je možné umístit i rozsahy a to buď číselné nebo písmenové. Například “[0-4a-cz]” – reprezentuje znaky 0, 1, 2, 3, 4, a, b, c, z.

Opakem je výčet s prvním znakem ^ ve formátu. “[^výčet znaků]”. V tomto případě znak stříšky neoznačuje začátek řetězce, ale negaci výčtu – tedy zastupuje libovolný znak, krom těch ve výčtu (například “[^0-9]” zastupuje všechny znaky, krom čísel).

Element pojmenovaných skupin

S tím, co již známe by jsme měli být schopni sestavit i velmi pokročilé regulární výrazy. Poslední co probereme ohledně zápisu RV budou pojmenované skupiny.

Pokud najdeme v textu shodu, dokážeme jí lokalizovat (podle indexu začátku shody). Ne vždy ale shoda je výsledek, který chceme získat. Jednoduchý příklad může být třeba ini soubor s řádky ve formátu “Klíč=Hodnota”. K nalezení stačí výraz “[^=]+=.+”. Jeho rozložením zjistíme, že hledá hodnotu začínající textem bez znaku “=”, pokračující právě znakem “=” a končí obyčejným textem. Výraz si můžeme rozložit na skupiny: “([^=]+)=(.+)”, funcionalita zůstává stejnou. Nyní zapíšeme definice pojmenované skupiny za otevírací závorky skupiny ve formátu “?<jméno skupiny>” – tím ji pojmenujeme. Můžeme to udělat třeba takto: “(?<klíč>[^=]+)=(?<hodnota>.+)”.

To znamená, že pokud prozkoumáme text “Resolution=1280x1024”, získáme shodu ve které najdeme 2 pojmenované skupiny s hodnotou “klíč”=”Resolution” a “hodnota”=”1280x1024”. Díky tomu máme již i shodu rozdělenou na části, které nás budou zajímat a které můžeme rovnou přečíst.

Jak skupiny číst si ukážeme v kapitole implementace.

Přehled regulárních výrazů s příklady

Nakonec slibovaný stručný přehled všech důležitých elementů regulárních výrazů:

Výraz Popis Příklad výrazu Odpovídající řetězce
^ Začátek textu ^abc abc, abcd, abc123…
$ Konec textu x$ abcx, x, aaax…
(…) Logická skupina (123)+ 123, 123123, 123123123…
[…] Výčet možných znaků [0-9] 1, 2, 4, 5, 6…
[^…] Obrácený výčet znaků [^0-9] a, b, z, x…
{…} Pevný počet výskytů ab{3}c abbbc
{…,…} Rozsah počtu výskytů ab{1,2}c abc, abbc
{…,} Minimální počet výskytů ab{2,}c abbc, abbbc, abbbbc…
* Žádný nebo více znaků A*hoj hoj, Ahoj, AAhoj, AAAhoj…
+ Jeden nebo více znaků A+hoj Ahoj, AAhoj, AAAhoj…
? Žádný nebo jeden znak A?hoj Ahoj, hoj
(?<…>…) Pojmenovaná skupina (?<skupina>[0-9]+) 1, 4, 53, 634…
…|… Alterace - více možností A(hoj|uto|aa) Ahoj, Auto, Aaa
. Libovolný znak (krom \n) A.oj Aaoj, Aboj, Acoj, Adoj…
\t Zastupuje znak tabulátoru    
\r Zastupuje návratu hlavy    
\n Zastupuje nový řádek \r\n {konec řádku}
\w Ekvivalent [a-zA-Z_0-9] \w+ sba34, 45, A1, fgBc…
\W Ekvivalent [^a-zA-Z_0-9] \W+ \, –, +, *…
\d Ekvivalent [0-9] \d+ 753, 4, 678, 3…
\D Ekvivalent [^0-9] \D+ ahoj, abc, df…
\s Zahrnuje neviditelné znaky    
\S Zahrnuje viditelné znaky \S+ Ahoj123, asd-dgg, fb…

Přehled jsem sestavil na základě http://regexlib.com/CheatSheet.aspx.

Implementace v .NET

Vždy budeme vycházet ze třídy System.Text.RegularExpressions.Regex. Její Instance reprezentuje vykompilovaný výraz. Nabízí několik statických metod pro přímý dotaz na shody bez zbytečného kódu okolo:

' vykompilovat a spustit RV
Dim shody = System.Text.RegularExpressions.Regex.Matches("řetězec", "výraz")

Pokud ale voláme stejný RV vícekrát, raději vytvoříme jeho instanci jen jednou. Ta má pak prakticky identické metody jako jsou ty statické. Jen ušetříme čas parsování výrazu a jeho kompilace:

' vykompilování výrazu
Dim regex As New System.Text.RegularExpressions.Regex("výraz")

Dim shody1 = regex.Matches("řetězec 1") ' spustit vykompilovaný RV proti textu
Dim shody2 = regex.Matches("řetězec 2") ' spustit vykompilovaný RV proti textu
Dim shody3 = regex.Matches("řetězec 3") ' spustit vykompilovaný RV proti textu

V případě, kdy chceme vrátit jen první shodu, použijeme místo Matches jen Match.

A když nepotřebujeme vědět podrobnosti o shodách, ale jen jestli odpovídá, použijeme IsMatch:

Dim shodujeSe = System.Text.RegularExpressions.Regex.IsMatch("Ahoj! Jak je?", "^Ahoj")

Další funkce, kterou jsem zatím nezmiňovat je nahrazování pomocí Replace. Ta nahradí všechny shody za zadaný text, například:

Dim nahrazenyText = System.Text.RegularExpressions.Regex.Replace("Ahoj! Jak je?", "^Ahoj", "Nazdar")
' vrátí z původního "Ahoj! Jak je?" zaměněný řetězec "Nazdar! Jak je?"

Vraťme se ale ke kolekci shod. Uchovávají se v MatchCollection a jsou datového typu Match. Když neobsahují žádnou položku (Count = 0), nenastala žádná shoda. Pokud ale nastala a shody procházíme, budou nás zajímat tyto vlastnosti:

  • Index – počáteční index znaku ve vstupním textu, kde byla shoda nalezená
  • Length – textová délka shody
  • Value – řetězcová hodnota, která reprezentuje text shody
  • Groups – hodnoty pojmenovaných i běžných skupiny

Pro ukázku uvádím kód, co najde všechny slova v textu. Použil jsem regulárního výrazu “\w+”, tedy 1 a víe písmen bez mezer a jiných oddělovačů, tím způsobem lze snadno najít oddělené skupiny písmenek – slov:

' vstupní text
Dim text As String = "Ahoj, tohle je ukázkový text. Jsou to dvě věty!"
Console.WriteLine("Vstupní text: {0}", text)

' najít shody s RV hledající slova
Dim shody As MatchCollection = Regex.Matches(text, "\w+")

' projít a vypsat shody
For Each shoda As Match In shody
    Console.WriteLine("Nalezeno slovo na pozici {0}, text: {1}", shoda.Index, shoda.Value)
Next

Console.ReadLine()

A nakonec kód, který přečte pojmenované skupiny (použiji trochu upravený, již zmiňovaný výraz pro parsování INI souborů):

' text INI souboru se 2ma řádkama
Dim text As String = "Klíč1=Hodnota1" + Environment.NewLine + "Klíč2=Hodnota2"
Console.WriteLine("Vstupní text:")
Console.WriteLine(text)

' vyhledat řádky
Dim shody As MatchCollection = Regex.Matches(text, "^(?<klíč>[^=]+)=(?<hodnota>[^\r\n]+)?", RegexOptions.Multiline)

' projít a vypsat shody podle pojmenovaných skupin
For Each shoda As Match In shody
    ' načíst hodnoty pojmenovaných skupin
    Dim klic As String = shoda.Groups("klíč").Value
    Dim hodnota As String = shoda.Groups("hodnota").Value

    ' vypsat výsledek
    Console.WriteLine("Nalezen řádek s klíčem '{0}' a hodnotou '{1}'.", klic, hodnota)
Next

Console.ReadLine()

Ještě se pozastavím na parsovacím výrazem. Začínáme znakem “^”, tedy začátkem řádku. Pak vyhledáváme text klíče bez znaku “=”, až na “=” opravdu narazíme. Dále pokračujeme textem hodnoty, než narazíme na konec řádku (“\r\n”).

Způsoby spuštění regulárního výrazu

Každé vyhodnocení shod můžeme spustit s jinými příznaky. Je to nepovinný parametr funkcí Matches, Match, IsMatch, Replace. Příkad předání můžeme vidět v předchozím příkladu při volání funkce Matches. Nejdůležitější se mi jeví tyto tři:

  • RegexOptions.Multiline – text s více řádky, začátek řádku je při jeho použití možné identifkovat znakem počátku “^
  • RegexOptions.IgnoreCase – ignoruje se velikost písmen
  • RegexOptions.RightToLeft – text se prochází obráceně, z prava doleva

Závěr a soutěž

Jestli jste se dočetli až sem, je to obdivuhodné, děkuji za pozornost. Jakékoliv dotazy klaďte do diskuze, bral jsem to všechno dost rychle.

Soutěž o dvě knihy Visual Basic 2008! Build a program now je již uzavřena! Za úkol byly tyto 3 úlohy:

Úloha 1 – Napiště regulární výraz, který najde kdekoliv v textu tuto doslovnou větu: “Umístění je C:\Soubor.exe?

Řešení - “Umístění je C:\\Soubor\.exe\?” – znaky zpětného lomítka, tečky a otazníku se museli ošetřit únikovou sekvencí.

Úloha 2 – K čemu by se dal použít výraz: “^http://(?<path>.+)/(?<file>[^\?/]*)(?<query>\?.+)?$

Řešení – Tento výraz rozparsuje http URL adresu. Jméno serveru a adresář, do kterého se odkazujeme se vloží do pojmenované skupiny path, název souboru do file a případný query string do query.
Například “http://server.cz/slozka/podslozka/soubor.aspx?id=34” bude rozdělen na:
- path = ”server.cz/slozka/podslozka
- file = ”soubor.aspx
- query = ”?id=34

Úloha 3 – Napište RV, co vyhledá čas v textu ve formátu “06:48:23” a jednotlivé části přiřadí do pojmenovaných skupin nazvaných hodiny, minuty, vteriny.

Řešení – Dobře vyřešená úloha nekontrolovala jen výskyt dvojic čísel oddělených dvojtečkou, ale i jejich rozsahy. Víme, že hodiny budou v rozsahu 0-23, minuty 0-59 a vteřiny také 0-59. Uvádím identické úlohy od obou soutěžících – rozdíl je jen v zápisu:
- “(?<hodiny>[01]\d|2[0-3]):(?<minuty>[0-5]\d):(?<sekundy>[0-5]\d)
- “(?<hodiny>([01][0-9])|(2[0-3])):(?<minuty>[0-5][0-9]):(?<vteriny>[0-5][0-9])

Úspěšnými řešiteli byli Pavel Veselý a Viktor Langer. Gratuluji!

 

hodnocení článku

3 bodů / 3 hlasů       Hodnotit mohou jen registrované uživatelé.

 

Mohlo by vás také zajímat

Jednoduchý scheduler v .NETu

Asi to znáte – máte nějaký složitější systém na zpracování velkého objemu dat a čas od času potřebujete vykovat nějakou automatizovanou údržbu – typicky smazat všechny položky starší než několika dní. Možností, jak toho dosáhnout, je hodně. Snažil jsem se vymyslet něco jednoduchého a efektivního.

dotNETcollege: Prosincový večerní kurz – používáme TeamCity v praxi

Finální pozvánka na veletrh práce pro programátory Jobs Dev 2018

 

 

Nový příspěvek

 

Regexator - http://regexator.net

Ahoj, pro testování a vývoj regulárních výrazů doporučuji Regexator (zdarma ke stažení na http://regexator.net)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

C# fce

Dobrý den

Chci se zeptat,

Pokud mám připadně text typu:

''Label=ffsdf2ds999sdf2sd2fv4sd5r8s9s6; expires=Tue, 23 Sep 2012 09:20:48 GMT; path=/test/tst; domain=172.1.0.1;'' 

a použiju regularni vyraz: "(:?[0-9]{2}:?){3}"

Vystup z něho je "09:20:48"

což je v dobře,

ale pokud chci zístat hodnotu Label pomocí

regularního vyrazu "Label=.*; exp"

vrátí mi fce v C# text"Label=ffsdf2ds999sdf2sd2fv4sd5r8s9s6; exp"

není nějaký způsob jakpomocí regularního vyrazu osekat, avbych dostal jenom tu hodnotu?

Už mě napadlo, že můžu následně použít "replace" a nahradit/vymazat nepotřebné,

spíš mě ale zajímá jak se dá výstup z toho regulárního výrazu nějak upravit.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Na to se používají skupiny. Jsou ve článku popsané.

Například:

Label=(?<value>.*); exp

Pak si jen vyzvednete ze skupiny požadovanou hodnotu.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: Regulérní výrazy

Můžu se zeptat jestli je nějaký reg. výraz pro české znaky, podobně jako "\w" pro ty nediakritické. Nemohl jsem vypátrat

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: Regulérní výrazy

Zdravim ,

Dakujem za clanok, mam akurad poznamku k

Dim regex As New System.Text.RegularExpressions.Regex("výraz")

preco si to nazval regex ?? nebolo by lepsie regex1 alebo take nieco , potom mam zmetok co je nazov premennej a co je prikaz v ostatnych prikladoch.

Dakujem za pochopenie

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Hezký den,

názvy tříd začínají velkým písmenem a jinak se v editoru zvýrazňují. Proto jsem nepovažoval za důležité rozlišovat název. Ale jistě je pravda, že pokud bude mít regulární nějaký specifický účel, je lepší jej pojmenovat podle něj. Například emailAddressRegex etc.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: Regulérní výrazy

Pokud máte problémy se skládáním regulárních výrazů, pomůže vám program zvaný "The Regex Coach". Já jsem se díky němu regulární výrazy naučil...

http://weitz.de/regex-coach/

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tiež existuje program RegexBuddy

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: Regulérní výrazy

+ Jeden nebo více znaků A?hoj Ahoj, AAhoj, AAAhoj…

V tabulce máš místo A+hoj A?hoj

Jinak regulární výrazy asi nikdy nepochopim.

Zkouším najít další slovo za jedním danným a nejde mi to, i když to tady vpodstatě je udělaný :-(

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Znak určení počtu (+, ?, {3}, atp.) se váže na předchozí znak (nebo skupinu znaků, pokud jsou v závorce). Z toho důvodu se ve výrazu A+hoj vážeme na pímeno A. Znamená to tedy Ahoj s jedním nebo více počátečním A.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

No právě. Ty tam máš místo toho A?hoj

Asi překlep

Problém se slovem jsem vyřešil. Asi nesmím být tak netrpělivý a počkat, až to můj pomalý ochablý mozek vstřebá

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Už to vidím, díky za upozornění. Opraveno.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: Regulérní výrazy

Zdravím,

dovolím si ještě připojit další ukázku na Replace. Oproti Replace v článku je lepší v tom, že můžeme text nahradit v závislosti na tom, jaký je Match. Následující kód najde v textu čílo a zvýší ho o 1:

Imports System.Text.RegularExpressions

Public Class Form1

    Private Sub Increase()
        Dim str As String = "Číslo 1 bude zvýšeno na 2."
        Dim rex As String = "\d+"
        MsgBox(Regex.Replace(str, rex, New MatchEvaluator(AddressOf NumberMatchHandler)))
    End Sub

    Private Function NumberMatchHandler(ByVal m As Match) As String
        Dim n As Integer = CInt(m.Value)
        Return (n + 1).ToString()
    End Function
End Class

Doufám, že to někomu pomůže. Já to hledal šíleně dlouho.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Díky, hezká ukázka. V článku jsem také vůbec neuvedl odkazy na skupiny v rámci výrazu. Ale myslím, že pro začátek to stačí.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ještě jedna drobnost. "\w" je "[a-zA-Z0-9_]". V článku podtržítko chybí.

PS: Oprava, podtržítko samozřejmě nechybí, jen je jinde, než jsem čekal a tak jsem jej přehlédl. Omlouvám se.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Díky, mně to pomohlo, Honza.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Diskuse: Regulérní výrazy

Naprosto souhlasím že Regular Expressions je velmi mocný nástroj pro práci s textem, avšak jeho neskutečná komplikovanost ho činí prakticky nepoužitelným. Považte jen obyčejnou validaci e-mailové adresy:

^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$

nahlásit spamnahlásit spam 3 / 3 odpovědětodpovědět

No validace emailové adresy regexem je zrovna jedna z mých trochu neoblíbených praktik. Pokud by měla být kompletní, měla by obsahovat i všechny domény prvního řádu a kontrolovat tunu dalších věcí.

Jinak souhlasím, že komplikovaný je, proto ho raději využívám na jednoduché věci. Nesmí se to s ním přehánět.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Regexpy jsou pěkné, ale opravdu by se neměly cpát všude. Nejhorší je, že dost lidí je používá i tam, kde by se používat neměly, například pro validaci datumu. Vypadne z nich něco jako ^[1-3]?[0-9]\.[01]?[0-9]\.[12][0-9]{3}, což je samozřejmě špatně, protože tam projde datum 35. 18. 2000, což je nesmysl.

Na druhou stranu na hledání složitějších věcí v textu nebo na provádění složitějšího nahrazování je to k nezaplacení. Dokonce i Visual Studio umí nahrazovat pomocí Regexpů.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ten příklad z datumem je takový divný, regexy na validace takových složitějších struktur jsou nepoužitelné (validace je možná jen za pomocí výpočtů - přestupné roky zejména.

Regexem velmi často nezískáme 100% řešení, proto musíme brát v potaz možné chyby ve vstupu a zaměřit se na ně.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Diskuse: Regulérní výrazy

Na problematiku regulárních výrazů se diskutuje snad na každé vývojářské komunitě, tento článek do toho určitě vnese laikům jasno....

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Áno, vniesol.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback