Regex Deel 3 – De puntjes op de i

Zoals je in het vorig deel hebt kunnen lezen is de regular expression tester te gebruiken om je regex kennis te praktiseren en expressies uit te testen.

Speciale karakters

Begin van een woord matchen

Het speciale karakter “\b” match een begin van een woord. Hebben we te doorzoeken tekst “Jan loopt met an in het bos met zijn os.” dan vinden we met de volgende reguliere expressie alleen een match op het woord “os”:

Een match op de naam “an” maar niet op “Jan” (in dit voorbeeld zonder hoofdletters) verkrijgen we door:

Om op elk woord een match te krijgen kan de volgende expressie worden gebruikt:

Match op alle karakters

De “.” staat voor een match van alle karakters behalve row breaks en new line karakters:

Bovenstaande matcht de volledige tekst. Overigens heeft de punt (“.”) binnen een karakterklasse (“[.]”) geen speciale betekenis.

Carriage return, Line Feed en Tab

Carriage return en Line Feed worden binnen regex hetzelfde aangeduidt als binnen .NET strings.
De carriage return:

De line feed:

De tab:

Bij het matchen van meerder regels binnen een tekst zijn de karakters van groot belang.

Alternatieven (Alternation)

Binnen karakterklassen wordt er gematcht op karakters binnen de klasse. Dit werkt altijd als een OF. Buiten de klassen wordt standaard als EN gematcht. Een OF match maken op “maandag” of “dinsdag” of “woensdag” gaat via de volgende reguliere expressie:

De haken groeperen de opdracht. De pipes (“|”) zorgen voor de OF instructies.

Case (in)sensitive

Bovenstaande reguliere expressie maakt alles wat volgt case insensitive. De regulier expressie “(?i)jan” op de te doorzoeken tekst “Jan loopt in het bos” resulteert in een match op “Jan”.
Bovenstaande expressie heft case insensivity weer op.

Gretig of lui repeteren

Stel we hebben de tekst “Jan loopt in het bos. Hij speelt op zijn contrabas.” Als we elke zin willen matchen kunnen we de volgende reguliere expressie maken:

Dit zal resulteren in 2 resultaten (gebruik tab 2 in de test tool). Dit is een voorbeeld van Greedy repetition. Het matchende resultaat wordt zo lang als mogelijk.
Voegen we echter een “?” aan het speciale repetitiekarakter (“+”) dan schakelen we over naar lazy repetition:

Dit resulteert in 49 resultaten, voor elke letter en spatie 1 resultaat. Zodra er een match is is het afgelopen.

Vooruit en achteruit kijken

Het is mogelijk een match te maken op onderdelen in de tekst zonder ze mee te nemen in het resultaat. We hebben de tekst “Jan loopt in het bos.”. We willen een match op alles wat komt na de tekst “Jan”.

.* staat voor alle karakters. ?<=Jan is een lookbehind naar de tekst “Jan” zonder deze mee te nemen in het resultaat.
Willen we een match op alles wat komt voor de tekst “bos” dan gebruiken we de volgende regex:

Een combinatie van beide is:
(?<=Jan).*(?=bos)
Alles tussen “Jan” en “bos” wordt gematcht.

Groeperen, verschillende resultaten in een keer matchen

In de tekst: “12 december 2010 19:34:44.999” zouden we bijvoorbeeld de dag en maand + het uur en de minuten kunnen halen. Groepen met namen zijn hier de oplossing. Zo kunnen in een keer op verschillende onderdelen van de tekst matches accuraat worden opgehaald. Dit is vooral handig bij het gebruik in .NET code. Een voorbeeld volgt iets verderop in dit artikel.

De syntax:

binnen de ronde haken zorgt voor naamgeving van een groep. In .NET bevat elke match een groepcollectie waarin de namen en resultaten zijn terug te vinden.

Gebruik van reguliere expressies in .NET

Zoals in de eerste deel van de regex artikelen aangegeven bevindt de regex functionaliteit zich binnen .NET in de System.Text.RegularExpressions namespace. De methode die vooral worden gebruikt voor het valideren en zoeken in de class Regex zijn:

 

  • IsMatch(string Text, string RegexPattern) resultaat Boolean
  • Matches(string Text, string RegexPattern) resultaat MatchCollection object

 

Belangrijk is om NIET te vergeten de patterns te escapen:

Wordt in code:

Bij het gebruik van de Matches functie wordt een MatchCollection object geretourneerd. Dit is een collectie met alle gevonden matches (Match objecten). De gevonden frase kan worden terug in de value property van het Match object.

Zoals eerder genoemd kan het gebruik van groepsnamen heel handig zijn. In het derde tabblad van de regular expression tester kun je testen met groepen. Voorbeeld:

Conclusie

Er is nog veel meer te vertellen over regular expressions. Ik hoop dat dit helpt om een eind op weg te komen met regular expressions. Echt de puntjes op de spreekwoordelijke “i” ?. Het boek: Mastering Regular Expressions van O’Reilly vond ik heel leerzaam, het behandeld ook de toepassing van reguliere expressies in .NET.

Vragen of opmerkingen? Aarzel niet, elke reactie is van harte welkom!

Regex Deel 2 – Quick start

Om direct met de regels aan de slag te kunnen die we hieronder gaan bespreken is het handig de snoei.net Regex Tester silverlight applicatie te gebruiken. Denk nu vooral niet dat dit een hele spannende applicatie is. Het stelt weinig voor, net zoals het gebruik van reguliere expressies binnen het .NET framework.

Door veel softwareontwikkelaars worden regular expressions gebruikt voor de validatie van velden zoals e-mailadres, url, postcode etc… Voor het zoeken van gegevens in grote stukken tekst wordt regex over het algemeen minder gebruikt. De manier waarop regex wordt gebruikt verschilt in beide gevallen niet veel van elkaar. Op beide zijn dezelfde regels van toepassing. We beginnen met de uitleg voor het doorzoeken van tekst. Het valideren van gegevens is dan appeltje/eitje.

In de voorbeelden hieronder worden dubbele quotes (“) gebruikt om een bepaalde tekst, frase of regex aan te duiden. Neem deze dus niet mee in de tests.

Hieronder overzichtelijk een aantal voorbeelden met een stuk tekst en een regular expression om bepaalde gegevens uit de tekst te halen.

Voorbeelden

‘Gewone’ karakters (literals) gebruiken

Tekst: “Jan loopt in het bos”
Zoekopdracht: Komt het woord: “loopt” voor?
Regex:

Uitleg: Voer dit bovenstaande voorbeeld in in op het eerste tabblad van de regular expression tester. Resultaat: een match. Het woord “loopt” komt tenminste 1 keer voor.

Het gebruik van ^ en $

Tekst: “Jan loopt in het bos.”
Zoekopdracht: Bevat de zin exact “Jan loopt in het bos.”?
Regex:

Uitleg: Het dakje (“^”) duidt aan dat de daaropvolgende tekst aan het begin van de te doorzoeken tekst moet staan. De reguliere expressie “^Jan” levert bijvoorbeeld een match op bij alle teksten die beginnen met “Jan”. Het dollar-teken (“$”) duidt het einde van de tekst aan. De regex “bos.$” levert een match op bij alle teksten die eindigen met “bos.”. Deze 2 in combinatie gebruiken betekent dat alles tussen deze 2-tekens exact overeen moet komen met de te doorzoeken tekst. Herkenbaar? Ja, deze worden bijna altijd samen gebruikt bij validaties.

Omzeilen van speciale karakters
^ en $ zijn dus speciale karakters en geen literals. Als met speciale tekens toch als literals wil gebruiken. Stel je wil een match maken op een dollar teken. Plaats dan een “\” voor het speciale teken. Dus tekst: “$500,-“, regex: “\$500,-” geeft een match.

Wat is een karakter klassen (character classes)

Tekst: “Jan loopt in het bos. Hij speelt op zijn contrabas.”
Zoekopdracht: De termen “bos” en “bas”.
Regex:

Uitleg: Gebruik voor deze test het tweede tabblad van de Regular Expression tester.

Er zijn 2 resultaten, “bos” en “bas”. We maken gebruiken van de zogenaamde character classes. Character classes zijn verzamelingen van karakters die worden omsloten met rechte haken (“[” en “]”). Een karakter klasse definieert welke karakters mogen voorkomen op een bepaalde positie binnen de tekst. In dit geval mag “o” OF “a” voorkomen op een plek tussen “b” en “s”. Het wordt “boos”, “boas” of “baas” zal dus niet in de zoekresultaten voorkomen omdat het hier slechts om 1 positie gaat.

Karakter klassen en karakterreeksen (a-z A-Z)

Tekst: “Jan loopt in het bos. Hij speelt op zijn contrabas.”
Zoekopdracht: Alle termen die beginnen met een “b” en eindigen op een “s” met daartussen 1 ander willekeurig karakter.
Regex:

Uitleg: a-z duiden alle kleine letters in het alfabet aan. A-Z alle hoofdletters. “b[a-z]s” zou dus alleen resulteren in een match als er een kleine letter tussen de “b” en de “s” staan. Alle reeksen op een rij:

a-z Kleine letters van “a” tot “z”. Mogelijke variatie: “a-f” = alle kleine letters van “a” tot en met “f”.
A-Z Hoofdletters van “A” tot en met “Z”.
0-9 Alle cijfers van “0” tot en met “9”.
\d Cijfers.
\w Alle woord karakters (alle alfanumerieke karakters inclusief underscore “_”).

Uitsluiten van karakters in een klasse

Tekst: “Jan loopt in het bos. Hij speelt op zijn contrabas.”
Zoekopdracht: Alle termen die beginnen met een “b” en eindigen op een “s” met daartussen 1 ander willekeurig karakter behalve de “a”.
Regex:

Uitleg: Het dakje (“^”) binnen een karakterklasse heeft een geheel andere betekenis als daarbuiten (begin van de te doorzoeken tekst). Met het dakje binnen een karakterklasse wordt een uitsluiting aangeduidt. Er is 1 resultaat: “bos”.

Karakter klasse en herhaling

Tekst: “Jan loopt in het bos. Hij speelt op zijn contrabas.”
Zoekopdracht: Alle termen die beginnen met een “l” en eindigen op een “pt” met daartussen een willekeurig aantal karakters.
Regex;

Uitleg:Direct achter een karakter klasse kan een herhaling worden aangeduid. “+” staat voor 1 of meer. In dit geval matcht “loopt” omdat tussen “l” en “pt” 1 of meerdere o’s voorkomen.

+ 1 of meer
* 0 of meer
{x} (vb. {3}) x aantal keer zoals aangeduid. (vb. 3 keer)
{x,y} (vb. {1,3}) x tot y keer. (vb. 1 tot 3 keer)
\w Alle woord karakters (alle alfanumerieke karakters inclusief underscore “_”).

Conclusie

Een hoop informatie. Met deze informatie zou je al behoorlijk uit de voeten moeten kunnen met regulier expressies. In het 3de een laatste deel de puntjes op de i met betrekking tot reguliere expressies.

In deel 3:

 

  • Alternation
  • Ankers (Anchors)
  • Special Characters
  • Reguliere expressies in .NET
  • Groeperen

 

Heb je vragen? Stuur een reactie.

Regex Deel 1 – Wat zijn Regular Expressions?

Regular Expressions, Wikipedia zegt er het volgende over:

Een reguliere expressie (afgekort tot “regexp”, “regex” of RE) is een manier om patronen te beschrijven waarmee een computer tekst kan herkennen. Er bestaat hiervoor een formele syntaxis, die grotendeels gestandaardiseerd is.

Kortom regular expressions zijn een krachtige manier om teksten te doorzoeken. Iets om niet zomaar naast je neer te leggen. Een krachtiger taal om tekst te doorzoeken is er bijna niet. Regex worden veel gebruikt voor de validatie van datainvoer zoals het verifiëren van e-mail invoer, numerieke invoer, datums (data ;-)) etc…

Wat ik persoonlijk de moeilijkheid aan regex vond is het onthouden van de regels die erbij horen. Regex is typisch iets wat je in vlagen gebruikt. Zit er een wat langere tijd tussen het toepassen ervan dan zakt alle kennis weer weg. In eerste instantie lijken regular expressions behoorlijk ingewikkeld. Dat dat best meevalt zul je kunnen lezen in de rest van de serie.

Het mooie is dat regex ook in Microsoft .NET goed wordt ondersteund. De regex functionaliteit is terug te vinden in de namespace System.Text.RegularExpressions.

Een goed startpunt is de .NET regular expressions testapplicatie. In deel 2 aandacht voor het het onder de knie krijgen van de regels met behulp van de Snoei.net Regex Tester. Deze Silverlight testapplicatie is een handig hulpmiddel voor mensen die minder van lezen houden en meer van ‘hands-on’ oplossingen.

C# codevoorbeeld:

Nieuws Radar NL App voor Android

Het is alweer een tijdje stil op m’n blog, maar ik zelf heb daarentegen niet stil gezeten. Als je brein elke dag bezig is om goede ideeen te ontdekken, kom je soms nog wel eens op een leuk idee. Dit geldt (vindt ik zelf) voor dit nieuwste telg: de Nieuws Radar app die sinds vandaag op de Android store staat.

Did you know that: Facebook uses the raw HTML of their mobile website http://m.facebook.com to provide content for their native iOS app.

Conversie van (nullable) valuetypes

Convert.pngJe kent het wel, je wilt de conversie van het ene naar het andere valuetype doen. Bijvoorbeeld een string omzetten naar een int. Gebruikelijk is om dat te doen met de volgende code:

Een andere optie is:

Deze laatste methode kan handig zijn als gebruik wordt gemaakt van reflection. Je weet dan vaak niet vooraf om welke bron en/of doeltypes het gaat.

Het type van MyProperty is onbekend maar zolang de string “881974” geconverteerd kan worden naar het type MyPropertyType is er geen probleem. Als MyPropertyType een string, decimal, int, float etc… is gaat het goed. Is het een bool dan gaat het uiteraard mis.

Allemaal heel mooi natuurlijk, maar deze Convert functies bieden geen ondersteuning voor nullable types. Willen we een bijvoorbeeld een string omzetten naar een int? (nullable int) dan hebben we een probleem. Tot nu toe, want hier is een oplossing ;-).

Bovenstaande functie ondersteund de conversie van nullable types. Wil je een echt elegante oplossing dan kunnen we met behulp van Generics de volgende methode maken binnen dezelfde DoConvert klasse, namelijk:

Je gebruikt deze functie als volgt:

Voila!

Html2Xhtml & Screen Scraping

HTML.pngWil je echt leuk informatie van het web plukken dan is die vaak niet toegankelijk via RSS. Neem bijvoorbeeld de site jaap.nl. Zoek je een koophuis dan moet je bij Jaap zijn en niet meer bij Funda. Want wat doet Jaap, Jaap scraped alle webpagina’s van Funda om de inhoud vervolgens op hun eigen website te publiceren. Scrapen is een methode om de voor jou doel relevante gegevens uit een (in dit geval) webpagina “te vissen”. Beleg je, dan is het bijvoorbeeld leuk om aan koersinformatie te komen. Denk maar niet dat die als RSS beschikbaar is. De gegevens zijn wel beschikbaar op openbaar toegankelijke webpagina’s van bijvoorbeeld morningstar.nl.

Nu is het voordeel van RSS dat het een XML standaard is en XML is gemakkelijk te gebruiken. HTML is echter een heel ander verhaal. HTML stelt lagere eisen aan consistentie en is daarom ook moeilijker te intepreteren. Wil je een HTML scrapen dan kun je voor de optie kiezen dit met behulp van regular expressions te doen. Ik heb zelf echter altijd het probleem dat ik vergeet hoe de syntax ook al weer was voor bepaalde zoekcriteria. Enkele jaren geleden heb ik daarom een setje klasses geschreven die HTML naar XML converteren. (Onder dit artikel vind je een link naar de download) Vervolgens kun je de gegevens in de HTML gemakkelijk parsen met behulp van bijvoorbeeld een XmlDocument object. Let op, het is geen rocket science maar het werkt en ik ben nog geen pagina tegengekomen die niet met de klasses kon worden geintepreteerd. Het is geen probleem als tags in de HTML die je om wil zetten niet worden gesloten (zoals bijv <P> of <BR>). De classes zorgen zelf dat dit op de juiste manier in de XML wordt afgehandeld.

Hoe werkt het?

Vervolgens kun je je uitleven op elke willekeurige pagina, van het KNMI tot flitsinformatie.

Download Html2XHtml.zip

Wat is een Lambda Expression?

LambdaExpressions.pngDe Lambda Expression is 1 van de nieuwe taalfeatures van C# 3.0. De nieuwe Visual Studio gaat hier ondersteuning voor bieden. Wat is een Lambda Expression eigenlijk?

Delegates
Even terug naar C# 1.0, daar begon het allemaal met delegates. Een delegate is eigenlijk een blauwdruk van een methode. Bijvoorbeeld

Bovenstaande delegate beschrijft een functie die een Person object als parameter verwacht en een boolean teruggeeft. Vervolgens kan er een functie worden gemaakt die met de delegate overeenkomt. Bijvoorbeeld:

Het voordeel van een delegate is dat de implementatie van de functie onafhankelijk is van de delegate blauwdruk. Zo zou de volgende implementatie ook prima overeenkomen met de genoemde delegate.

We kunnen met onderstaande methode de resultaten van beidde delegate implementaties testen:

Bovenstaande functie roepen we in C# 1.0 als volgt aan:

Delegates worden ook gebruikt in het event model van het .NET framework. In dat geval praten we over EventHandlers. Aangezien bovenstaande oplossing vrij omslachtig is als het gaat om een vrij simpele implementatie van een functie op basis van een delegate is er in C# 2.0 de anonymous method geintroduceerd.

Anonymous Methods
Dankzij de Anonymous Method hoeven we in bovenstaande geval geen specifiek implementatie te schrijven voor de IsTrue delegate maar kunnen we de FirstNameStartsWithT test als volgt formuleren:

Het grote voordeel, de inhoud van de functie FirstNameStartsWithT kan direct worden meegegeven zonder er een specifieke method te hoeven schrijven, een anonieme methode dus…

Lambda Expressions
Aangezien dit ook nog een redelijk omslachtige schrijfwijze is heeft men in C# 3.0 de Lambda Expression geintroduceerd. Syntactisch worden als eerste de parameters benoemd, benaming naar eigen keuze. Dan volgt “=>” daarna volgt de implementatie zoals in het bovenstaande delegate en anonymous method voorbeeld. Dus..

Deze korte schrijfwijze heeft zijn effect op de LINQ implementatie. Het is echter de vraag of dat dankzij de Lambda Expression mogelijk werd of dat de Lambda Expression zijn bestaan dankt aan de LINQ implementatie 😉 Ach, dat zullen we nooit weten…

LambdaExpressionsTest.zip – Voorbeeldcode voor Visual Studio Orcas Beta 1

WPF, WPF/E, Silverlight en XBAP

WPF.JPGIk ben al een tijdje in mijn vrije tijd aan het rommelen met WPF. De termen vliegen om je oren, maar wat is wat, waarvoor en hoe. Kortom dat kwam na een tijdje bij mij boven borrelen. Na wat zoekwerk heb ik het een en ander op een rijtje.

WPF is door Microsoft gelanceerd als de opvolger van het al verouderde WinForms ontwikkelmodel. WPF staat voor Windows Presentation Foundation, voorheen Avalon genoemd. Belangrijkste vooruitgang die met de introductie van WPF wordt geboekt is dat presentatie en logica nu strikter gescheiden zijn. De presentatie kan nu theoretisch gesproken gemakkelijker gebeuren door designers terwijl de businesslogic door de developers kan worden gedaan. In WPF worden windows (vergelijkbaar met forms) volledig beschreven in XAML een op XML gebaseerde taal. WPF combineert de kracht van 2 werelden. WinForms, het sterk interactieve model en Web dat geen beperkingen legt op vormgeving. WPF gaat nog verder, mogelijkheden als een roterend filmpje in een item van een listview zijn makkelijk te realiseren. Het is bovendien ook niet heel moeilijk zelf controls te bouwen. Een goed boek over WPF is Applications = Code + Markup van Charles Petzold. Met tools als Microsoft Expression Studio (met name Blend) kunnen gemakkelijk WPF applicaties gebouwd worden. Maar ook in de komende versie van Visual Studio, Visual Studio codename Orcas beschikt over mogelijkheden tot het maken van de diverse soorten WPF applicaties.

WPF/E, WPF Everywhere sinds kort officieel Silverlight genoemd. WPF/E bevat een subset van WPF met alleen de presentatielaag. De gestripte versie bevat bijvoorbeeld enkel een TextBlock control en geen button, listbox en welke andere controls dan ook. WPF/E is bedoeld voor het gebruik in browsers en biedt cross-platform ondersteuning. Het grote voordeel van deze gestripte versie is dat het in principe in een aantal browsers bruikbaar is middels plug-in van +/- 2Mb. Daarmee wordt meteen het voordeel duidelijk dat alleen de plug-in en niet het volledige .NET 3.0 framework op de client geïnstalleerd hoeft te worden (a 54Mb).

Bekijk deze Silverlight klok eens.. Wil je zelf aan de slag met Silverlight dan is dit een leuke tutorial om mee te beginnen.

XBAP, naast WPF/E is er ook nog de XBAP browser oplossing. XBAP staat voor XAML Browser Applications. Voor het gebruik van XBAP binnen de browser dient wel het volledige .NET 3.0 framework op de cliënt geïnstalleerd te zijn. Maar, dat heeft als voordeel dat WPF in al zijn facetten aanwezig en te gebruiken is. Ten opzichte van de “gewone” standalone WPF applicatie is er wel het verschil dat XBAP in een security sandbox draait waarbij rechten zijn ingeperkt zoals bijvoorbeeld toegang tot het bestandssysteem. Wil je een gecentraliseerde oplossing met een rijke GUI waarbij je bijvoorbeeld gebruik maakt van een webservice dan kan dit een prima mogelijkheid zijn.