6
Tags:
diverse
Skrevet af
Bruger #345
@ 26.08.2008
Konklusion
Nu da vi har fået kigget på alle elementerne i vores udtryk kan vi se det i forhold til udtrykket. En email ser jo som bekendt sådan her ud - user@host.tld - (tld står for top-level domain, eksempelvis .dk eller .com) og hvis vi kigger efter på den del af udtrykket før @ så finder vi det her; ^\w[\w.-]*. Med det vi har lært kan vi regne ud af den skal starte med et alfanumerisk tegn (enten et bogstav, et tal eller en underscore (_)) ligesom der kan forkomme et alfanumerisk tegn, et . eller en - på de næste placeringer. Næste tegn er selvfølgelig @ tegnet selv så det springer vi over. Efter det kommer (\w[\w-]*\.)+ som skal finde host navnet samt det afsluttende punktum, inden tld. Den gør det ved at næsten gentage udtrykket fra user delen undtagen at den sidste character class ikke har et . i sig. Den har vi placeret efter klassen for at sikre os at under-udtrykket slutter på et punktum. Derved vil det finde "a-host.", "minside." osv. men ikke "-site." eller "si.te". Det sidste vil mangler er [a-z]{2,4}$ som eneste opgave er at finde tld. Man kan, hvis man, erstatte det med det her udtryk; (dk|com|net)$ - hvis man vil begrænse udtrykket til bestemte top-level domains.
Eksempler
Vi skulle nu have været omkring nok af regex så udtrykket er forståeligt, så nu er det på tide at se hvordan vi bruger det i praksis. Sprogene er ikke valgt i nogen speciel rækkefølge og det er i flere af sprogene muligt at gøre det samme på flere forskellige måder, her har jeg dog valgt kun at vise en for hvert sprog. Eksemplerne er holdt ens for at man kan se forskelle/ligheder imellem de forskellige sprog.
.NET (C#)
- // Verbatim string så \ ikke skal escapes
- // RegexOptions.ECMAScript er for at slå Unicode understøttelse fra
- Regex pattern = new Regex(@"^\w[\w.-]*@(\w[\w-]*\.)+[a-z]{2,4}$", RegexOptions.IgnoreCase | RegexOptions.ECMAScript);
- string email = "en.em@il.her.dk";
-
- if(pattern.IsMatch(email))
- {
- Console.WriteLine("Det er en gyldig email!");
- }
Perl
- # Perl sætter dens regex indstillinger lige efter udtrykket, her er det i, som står for "ignore case"
- $pattern = q{^\w[\w.-]*@(\w[\w-]*\.)+[a-z]{2,4}$};
- $email = 'en.em@il.her.dk';
-
- if($email =~ m/$pattern/i)
- {
- print "Det er en gyldig email!";
- }
Python
- # coding: latin-1
- # Kommentareren ovenover er vigtig
- import re
- pattern = "^\w[\w.-]*@(\w[\w-]*\.)+[a-z]{2,4}$"
- email = "en.em@il.dk"
-
- if(re.search(pattern, email, re.IGNORECASE)):
- print "Det er en gyldig email!"
Ruby
# Se punkt 1 forneden, hvorfor ^ og $ er erstattet med \A og \Z
pattern = /\A\w[\w.-]*@(\w[\w-]*\.)+[a-z]{2,4}\Z/i
email = "en.em@il.dk"
if email =~ pattern
puts "Det er en gyldig email!"
end
PHP (?)
- # PHP bruger en mærkelig blanding af regex delimiters, både strings og //
- $pattern = "/^\w[\w.-]*@(\w[\w-]*\.)+[a-z]{2,4}$/i";
- $email = "en.em@il.dk";
-
- if(preg_match($pattern, $email))
- {
- echo "Det er en gyldig email!";
- }
JavaScript
- // JavaScript er kun istand til at finde starten på linjen, ikke strengen
- var pattern = /^\w[\w.-]*@(\w[\w-]*\.)+[a-z]{2,4}$/i
- var email = "en.em@il.dk";
-
- if(pattern.test(email))
- {
- alert("Det er en gyldig email!");
- }
Punkter
1. Visse elementer i regex opfører sig anderledes afhængigt af om de er sat til multiline-mode eller singleline-mode. Tre af disse bruger vi her i artiklen, ., ^ og $ (Undtagelsen her er Ruby og JavaScript, hvor de kun er i stand til at finde starten på linjen, ikke strengen). Deres opførsel i multiline er således:
- .: Den matcher alt, undtagen linjeskift
- ^: Matcher starten på en linje, det vil sige, lige efter et linjeskift
- $: Matcher slutningen på en linje, lige før linjeskiftet
Og så de samme, nu bare ved singleline:
- .: Den matcher alt, også linjeskit
- ^: Matcher starten på teksten, lige før det allerførste tegn
- $: Matcher slutningen på teksten, lige før det sidste linjeskift
Selvom ^ og $ ikke matcher starten og slutningen på teksten når multiline er slået til, så kan man godt opnå det alligevel ved at bruge \A og \Z respektivt, dog ikke i JavaScript, som ikke understøtter dem. De svarer til ^ og $ opførsel under singleline.
2. Blandt andet .NET har slået Unicode understøttelse til som standard, men dette kan let slåes fra med RegexOptions.ECMAScript, som ses i eksemplet foroven. I Perl bruger regex unicode fra version 5.6, men det kan omgåes ved at bruge q{} omkring regexen, som i eksemplet her i artiklen.
Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.
Del også gerne artiklen med dine Facebook venner:
Kommentarer (3)
Dine regexes virker ikke korrekt. Jeg brugte dem på listen af gyldige og ugyldige adresser fundet på
http://en.wikipedia.org/wiki/E-mail_address og fik en del forkerte svar:
Gyldig bc@example.com
Gyldig Abc@example.com
Gyldig aBC@example.com
Gyldig abc.123@example.com
Gyldig 1234567890@example.com
Gyldig _______@example.com
Ugyldig abc+mailbox/department=shipping@example.com
Ugyldig !#$%&'*+-/=?^_`.{|}~@example.com
Ugyldig "abc@def"@example.com
Ugyldig "Fred \"quota\" Bloggs"@example.com
Ugyldig Abc.example.dk
Gyldig Abc.@example.dk
Gyldig Abc..123@example.dk
Ugyldig A@b@c@example.dk
Ugyldig ()[]\;:,<>@example.dk
Alle .com adresserne er gyldige, mens alle .dk adresserne er ugyldige.
Hvis du så tog dig tid til rent faktisk at læse min disclaimer, så gør jeg opmærksom på lige netop dette. Mine regex her er lavet til at matche hvad generelt er tilladt, ikke hvad RFC 2882 specificere. Hvis jeg skal skrive en regex der matcher alle de ovennævnte blev den også for kompliceret til en introduktions artikel.
Men igen, alt det her har jeg rent faktisk skrevet i starten af artiklen... Hvis du havde taget dig tid til at læse den.
Og nu tog jeg mig så lige tid til at læse wikipedia siden. Det er rigtigt at . til sidst og dobbelt .. er tilladt, men igen, det overkompliciferer regexen lidt med look-around assertions som jeg slet ikke har berørt endnu. Det skal nok komme i en senere artikel, og så skal jeg nok omskrive regexen så den er mere gyldig. Men helt efter RFC specs bliver den altså aldrig, da det er meget sjældent nogen der tillader dem (selv om RFC forskriver det).
Du skal være
logget ind for at skrive en kommentar.