|
Dit artikel is gepubliceerd op zondag 31 juli 2011 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.
De complexiteit van de gebruikte reguliere expressies hangt altijd af van een aantal verschillende factoren.
De veronderstellingen die men kan maken over de input is één van deze factoren. Als men bijvoorbeeld een gegeven emailadres moet valideren, maar men reeds reeds zeker zou zijn dat het enkel geldige karakters zijn gebruikt ( bijvoorbeeld omdat het gebruikte invoertekstvak geen ongeldige karakters toestaat ), dan is het niet meer noodzakelijk om de verschillend mogelijke karakters in de reguliere expressie op te nemen.
Een ander belangrijke factor is het doeleinde waarvoor de gevonden matches worden gebruikt. In het lokale gedeelte ( voor @ ) van een emailadres zijn karakters als $ en ! nog altijd geldig. Vele mailservers en mailsoftware zullen deze echter niet ondersteunen.
Anderzijds moet men ook de overweging maken, of een algoritmische benadering niet performanter en eenvoudig te onderhouden is dan een complexe reguliere expressie. Stel dat men op zoek gaat naar alle keywords van een bepaalde programmeertaal, dan kan men in de reguliere expressie een alternation met een lange lijst van alternatieven opbouwen. Of dit echter makkelijk te onderhouden is, bijvoorbeeld bij aanpassing of uitbreiding van de taal, is dan weer afhankelijk van de manier waarop deze reguliere expressie in je applicatie wordt opgebouwd. 27.10.1. Double Quoted WordsZoeken en vervangen van dubbele woorden. Waarbij dubbele woorden, woorden zijn die twee maal voorkomen, en waar zich een whitespace tussen bevindt. Visual Basic 2010 Broncode Imports System.Text.RegularExpressions Class Example1 Public Shared Sub Main() Dim input As String = "A a double word word" For Each m As Match In Regex.Matches(input, "\b(\w+)\s+\1\b", _ RegexOptions.IgnoreCase) Console.WriteLine(m.Value) Next Dim output As String output = Regex.Replace(input, "\b(\w+)\s+\1\b", "$1", _ RegexOptions.IgnoreCase) Console.WriteLine(output) Console.ReadLine() End SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output A a
word word
A double word boven
27.10.2. Integer ValuesZoeken naar een woord dat bestaat uit een geheel getal vanaf 1 tot en met 9999 : Visual Basic 2010 Broncode Imports System.Text.RegularExpressions Class Example2 Public Shared Sub Main() Dim input As String = "0 1 5000 9999 10000" For Each m As Match In Regex.Matches(input, "\b[1-9][0-9]{0,3}\b") Console.WriteLine(m.Value) Next Console.ReadLine() End SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output 1
5000
9999 boven
27.10.3. Hexadecimale GetallenZoeken naar een woord die bestaat uit een hexadecimale waarde : Visual Basic 2010 Broncode Imports System.Text.RegularExpressions Class Example3 Public Shared Sub Main() Dim input As String = "0A 1F AAA 17 AG" For Each m As Match In Regex.Matches(input, "\b[0-9a-fA-F]+\b") Console.WriteLine(m.Value) Next Console.ReadLine() End SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output 0A
1F
AAA
17 boven
27.10.4. IdentifiersAls we van een tekst zouden nagaan of dit een geldige Visual Basic identifier is, moeten we ondermeer met volgende regels rekening houden :
- enkele de karakters 0-9, a-z, A-Z en _ ( underscore ) zijn toegelaten, de taal zelf is case-insensitive, de editor is echter wel case sensitive - niet beginnen met cijfer - als de identifier start met _ volgt hierop minimum 1 cijfer, letter of underscore - lengte maximaal 1023 karakters Visual Basic 2010 Broncode Imports System.Text.RegularExpressions Class Example4 Private Shared m_Pattern As String Public Shared Sub Main() m_Pattern = "(?i:^(?(?=_)_[a-z_0-9]{1,1022}|[a-z][a-z_0-9]{0,1022})$)" Print( "a") Print( "aA") Print( "a1") Print( "A_") Print( "_a") Print( "_1") Print( "__") Print( New String( "a", 1023)) Console.WriteLine() Print( " a") Print( "a ") Print( "a a") Print( "a-") Print( "1") Print( "_") Print( "1a") Print( "11") Print( "1_") Print( New String( "a", 1024)) Console.ReadLine() End Sub Public Shared Sub Print( ByVal input As String) Dim m As Match = Regex.Match(input, m_Pattern) If m.Success Then Console.WriteLine( """" & m.Value & """ is a correct identifier.") Else Console.WriteLine( """" & input & """ is not a correct identifier.") End If End SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output "a" is a correct identifier.
"aA" is a correct identifier.
"a1" is a correct identifier.
"A_" is a correct identifier.
"_a" is a correct identifier.
"_1" is a correct identifier.
"__" is a correct identifier.
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" is a correct i
dentifier.
" a" is not a correct identifier.
"a " is not a correct identifier.
"a a" is not a correct identifier.
"a-" is not a correct identifier.
"1" is not a correct identifier.
"_" is not a correct identifier.
"1a" is not a correct identifier.
"11" is not a correct identifier.
"1_" is not a correct identifier.
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" is not a corr
ect identifier. boven
27.10.5. Quoted Email ReplyEen orginele tekst van een email kunnen we in een reply laten voorafgaan door de tekst "> " : Visual Basic 2010 Broncode Imports System.Text.RegularExpressions Class Example5 Public Shared Sub Main() Dim email As String = "Hi John," & vbLf & vbLf & _ "How are you doing?" & vbLf & vbLf & _ "Greetings," & vbLf & _ "Jane" Dim quotedEmail As String quotedEmail = Regex.Replace(email, "^", "> ", RegexOptions.Multiline) Console.WriteLine(quotedEmail) Console.ReadLine() End SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output > Hi John,
>
> How are you doing?
>
> Greetings,
> Jane boven
27.10.6. Double Quoted TextIndien we op zoek gaan naar text tussen twee double quotes, dan zal het pattern "".*"" waar we de greedy * quantifier gebruiken, zoveel mogelijk karakters opleveren tussen twee double quotes.
Als we eerder zo weinig mogelijk ( 0 of meerdere ) karakters op dezelfde lijn tussen deze quotes wensen, dan kan men de pattern "".*?"" ( reluctant * ) of ""[^""]*"" ( negation charachter group ) gebruiken : Visual Basic 2010 Broncode Imports System.Text.RegularExpressions Class Example6 Public Shared Sub Main() Dim input As String = "one ""two"" three ""four five"" six" Console.WriteLine( "input : " & input) Console.WriteLine() For Each m As Match In Regex.Matches(input, """.*""") Console.WriteLine(m.Value) Next Console.WriteLine() For Each m As Match In Regex.Matches(input, """.*?""") Console.WriteLine(m.Value) Next Console.WriteLine() For Each m As Match In Regex.Matches(input, """[^""]*""") Console.WriteLine(m.Value) Next Console.ReadLine() End SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output input : one "two" three "four five" six
"two" three "four five"
"two"
"four five"
"two"
"four five" boven
27.10.7. Valid DatesIn onderstaand voorbeeld gaan we op zoek naar datums in een geldig formaat.
Het formaat dat hier gebruikt wordt, is : yyyymd. Het jaar ( vanaf 1900 tot en met 2099 ) bestaat altijd uit 4 cijfers, de maand bestaat uit 1 of 2 cijfers ( vanaf 1 tot en met 12 ) en de dag bestaat uit 1 of 2 cijfers ( vanaf 1 tot en met 31 ).
De delimeter mag een spatie, koppelteken, slash of punt zijn. Deze moet wel consistent zijn, waarvoor een backreference is gebruikt : Visual Basic 2010 Broncode Imports System.Text.RegularExpressions Class Example7 Public Shared Sub Main() Dim input As String input = "1899-01-01 1900-01-01 2099.12.31 2001-13-05" & _ "1900-2-3 2008 10 30 2008-9-32 1905-08/10" Dim year As String = "(19|20)\d\d" Dim month As String = "(0?[1-9]|1[012])" Dim day As String = "(0?[1-9]|[12][0-9]|3[01])" Dim pattern As String = year & "(?<delimeter>[ -/.])" & _ month & "\<delimeter>" & day For Each m As Match In Regex.Matches(input, pattern) Console.WriteLine(m) Next Console.ReadLine() End SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output 1900-01-01
2099.12.3
1900-2-3
2008 10 3
2008-9-3 Controles op aantal dagen van een bepaalde maand gebeuren hier niet, de tekst "2008-04-31" zal hier bijvoorbeeld matchen met bovenstaand pattern. Toch is dit geen geldige datum. Ook dit kan men in het pattern opnemen, net als controles op schrikkeljaren, maar deze zijn vele malen eenvoudiger te controleren in je code. boven
27.10.8. Trimming WhitespacesIn onderstaand voorbeeld worden alles spaties of alle soorten whitespaces aan het begin en op het einde van de inputstring verwijderd : Visual Basic 2010 Broncode Imports System.Text.RegularExpressions Class Example8 Public Shared Sub Main() Dim input As String Dim output As String input = " bla " output = Regex.Replace(input, "\A *| *\Z", "") Console.WriteLine( "escaped input : " & Regex.Escape(input)) Console.WriteLine( "escaped output : " & Regex.Escape(output)) input = vbLf & " bla " & vbLf output = Regex.Replace(input, "\A\s*|\s*\Z", "") Console.WriteLine( "escaped input : " & Regex.Escape(input)) Console.WriteLine( "escaped output : " & Regex.Escape(output)) Console.ReadLine() End SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output escaped input : \ \ bla\ \ \
escaped output : bla
escaped input : \n\ \ bla\ \ \ \n
escaped output : bla boven
27.10.9. Valid IP AddressZoeken naar een IP ( IPv4 ) adres : Visual Basic 2010 Broncode Imports System.Text.RegularExpressions Class Example9 Public Shared Sub Main() Dim input As String = "192.168.0.0" Dim pattern As String = "\b" & _ "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\." & _ "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\." & _ "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\." & _ "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b" Console.WriteLine( Regex.Match(Input, pattern).Value) Console.ReadLine() End SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output 192.168.0.0 boven
27.10.10. Valid Email AddressOok bij het valideren van emailadressen zal de complexiteit van de gebruikte reguliere expressie afhangen van de veronderstelling die men kan maken over de input. En afhangen van de doeleinden waarvoor de gevonden matches worden gebruikt. Zo zijn karakters als $ en ! geldige karakters in het lokale gedeelte ( voor de @ ) van een emailadres, maar sommige mailservers of mailsoftware in het algemeen zullen deze dan weer niet ondersteunen.
Onderstaand pattern zal zeker 99.99% van de gebruikte emailadressen correct valideren, maar een aantal emailadressen zullen niet door het pattern worden gevonden. Bijvoorbeeld emailadressen die double quoted local parts hebben, sommige mailservers ondersteunen adressen als "john smith"@example.com. Enkel de meest gebruikte en meest toegestane karakters worden hier in het pattern opgenomen. Ook IP adressen kunnen gebruikt worden als domain, het pattern zal ook deze niet ondersteunen. Anderzijds zullen ook een aantal foutieve matches gevonden worden. Er is hier geen volledige lijst opgenomen van alle mogelijke country-code top level domains ( ccTLDs ). Elke country-code mag hier bestaande uit 2 karakters uit het bereik a-z. Ook "aa" zou dan echter ook als een correcte ccTLD worden beschouwd, ondanks dat het een onbestaande ccTLD is. Er wordt wel een lijst opgenomen van alle huidige ( op moment van schrijven ) generic top level domains ( gTLDs ), deze is beperkt in omvang en wordt niet vaak aangepast, in tegenstelling tot het aantal ccTLDs die momenteel al meer dan 200 items bevat, en nog regelmatig wordt uitgebreid.
Of onderstaand pattern te complex of net te eenvoudig is, hangt dus op zijn minst af van de doeleinden van de gevonden matches. Visual Basic 2010 Broncode Imports System.Text.RegularExpressions Class Example10 Public Shared Sub Main() Dim local As String = "[a-z0-9%+_-]+(?:\.[a-z0-9%+_-]+)*" Dim SLD As String = "(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+" Dim ccTLD As String = "[a-z]{2}" Dim gTLD As String = "(>?aero|arpa|asia|biz|cat|com|coop|edu|gov|" & _ "info|int|jobs|mil|mobi|museum|name|net|org|" & _ "pro|tel|travel)" Dim TLD As String = "(?:" & ccTLD & "|" & gTLD & ")" Dim domain As String = SLD & TLD Dim email As String = "(?i:\b" & local & "@" & domain & "\b)" Dim input As String = "a0%+_-@a.museum a@b-c.de a.b.c@e.f.g.com" For Each m As Match In Regex.Matches(input, email) Console.WriteLine(m.Value) Next input = "a.@b.cd a(@b.cd a@b.xxx" For Each m As Match In Regex.Matches(input, email) Console.WriteLine(m.Value) Next Console.ReadLine() End SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output a0%+_-@a.museum
a@b-c.de
a.b.c@e.f.g.com
Dit artikel is gepubliceerd op zondag 31 juli 2011 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.
|