Regular Expressions
Handige Regex Showcase
Zoeken…
Match een datum
Je moet onthouden dat regex is ontworpen voor het matchen van een datum (of niet). Zeggen dat een datum geldig is, is een veel gecompliceerdere strijd, omdat hiervoor veel uitzonderingsprocedures nodig zijn (zie schrikkeljaarvoorwaarden ).
Laten we beginnen met het matchen van de maand (1 - 12) met een optionele voorloop 0:
0?[1-9]|1[0-2]
Om de dag te evenaren, ook met een optionele leidende 0:
0?[1-9]|[12][0-9]|3[01]
En om het jaar te evenaren (laten we uitgaan van het bereik 1900 - 2999):
(?:19|20)[0-9]{2}
Het scheidingsteken kan een spatie, een streepje, een schuine streep, leeg, etc. zijn. Voel je vrij om alles toe te voegen waarvan je denkt dat het als scheidingsteken kan worden gebruikt:
[-\\/ ]?
Nu voeg je het hele ding samen en krijg je:
(0?[1-9]|1[0-2])[-\\/ ]?(0?[1-9]|[12][0-9]|3[01])[-/ ]?(?:19|20)[0-9]{2} // MMDDYYYY
(0?[1-9]|[12][0-9]|3[01])[-\\/ ]?(0?[1-9]|1[0-2])[-/ ]?(?:19|20)[0-9]{2} // DDMMYYYY
(?:19|20)[0-9]{2}[-\\/ ]?(0?[1-9]|1[0-2])[-/ ]?(0?[1-9]|[12][0-9]|3[01]) // YYYYMMDD
Als je wat pedanter wilt zijn, kun je een terugverwijzing gebruiken om er zeker van te zijn dat de twee scheidingstekens hetzelfde zijn:
(0?[1-9]|1[0-2])([-\\/ ]?)(0?[1-9]|[12][0-9]|3[01])\2(?:19|20)[0-9]{2} // MMDDYYYY
^ refer to [-/ ]
(0?[1-9]|[12][0-9]|3[01])([-\\/ ]?)(0?[1-9]|1[0-2])\2(?:19|20)[0-9]{2} // DDMMYYYY
(?:19|20)[0-9]{2}([-\\/ ]?)(0?[1-9]|1[0-2])\2(0?[1-9]|[12][0-9]|3[01]) // YYYYMMDD
Overeenkomen met een e-mailadres
Het matchen van een e-mailadres binnen een string is een moeilijke taak, omdat de specificatie die het definieert, de RFC2822 , complex is, waardoor het moeilijk te implementeren is als een regex. Voor meer informatie waarom het geen goed idee is om een e-mail aan een regex te koppelen, raadpleegt u het voorbeeld van de antipatroon wanneer u geen regex gebruikt: voor het matchen van e-mails . Het beste advies om van die pagina op te merken, is om een peer-reviewed en brede bibliotheek in uw favoriete taal te gebruiken om dit te implementeren.
Valideer een e-mailadresindeling
Wanneer u een invoer snel moet valideren om er zeker van te zijn dat deze op een e-mail lijkt , kunt u het het beste eenvoudig houden:
^\S{1,}@\S{2,}\.\S{2,}$
Die regex zal controleren of het e-mailadres een niet-spatie gescheiden reeks tekens met een lengte van meer dan één is, gevolgd door een @
, gevolgd door twee reeksen niet-spaties tekens met een lengte van twee of meer gescheiden door een .
. Het is niet perfect en valideert mogelijk ongeldige adressen (volgens de indeling), maar het belangrijkste is dat het geen geldige adressen ongeldig maakt.
Controleer of het adres bestaat
De enige betrouwbare manier om te controleren of een e-mail geldig is, is om te controleren op het bestaan ervan. Vroeger was er de VRFY
SMTP-opdracht die voor dat doel is ontworpen, maar helaas, na misbruik door spammers is het nu niet meer beschikbaar .
Dus de enige manier om te controleren of de e-mail geldig is en bestaat, is om een e-mail naar dat adres te sturen.
Enorme Regex-alternatieven
Het is echter niet onmogelijk om een e-mail met een regex te valideren. Het enige probleem is dat hoe dichter bij de specificatie die regexen zullen komen, des te groter ze zullen zijn en bijgevolg onmogelijk te lezen en te onderhouden zijn. Hieronder vindt u een voorbeeld van een dergelijke nauwkeurigere regex die in sommige bibliotheken wordt gebruikt.
⚠️ De volgende regex wordt gegeven voor documentatie en leerdoeleinden, kopiëren en plakken in uw code is een slecht idee. Gebruik in plaats daarvan die bibliotheek rechtstreeks, zodat u kunt vertrouwen op upstream-code en peer-ontwikkelaars om uw e-mailparscode actueel en onderhouden te houden.
Perl Adres matching module
De beste voorbeelden van een dergelijke regex zijn in sommige talen standaardbibliotheken. Er is bijvoorbeeld een van de RFC::RFC822::Address
module in de Perl-bibliotheek die volgens de RFC zo nauwkeurig mogelijk probeert te zijn. Voor je nieuwsgierigheid kun je een versie van die regex vinden op deze URL , die is gegenereerd op basis van de grammatica, en als je in de verleiding komt om het te kopiëren en plakken, is hier een citaat van de auteur van de regex:
" Ik onderhoud de reguliere expressie [gekoppeld] niet. Er kunnen bugs in zijn die al in de Perl-module zijn opgelost. "
.Net adresmodule
Een andere, kortere variant is de variant die wordt gebruikt door de standaardbibliotheek .Net in de module EmailAddressAttribute
:
^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$
Maar zelfs als het korter is, is het nog steeds te groot om leesbaar en gemakkelijk te onderhouden te zijn.
Ruby Address matching module
In robijn wordt een samenstelling van regex gebruikt in de rfc822-module om een adres te matchen. Dit is een goed idee, want in het geval dat er bugs worden gevonden, zal het gemakkelijker zijn om het regex-onderdeel te lokaliseren om het te wijzigen en te repareren.
Python Adres matching module
Als een tegenvoorbeeld, gebruikt de python email parsing module geen regex, maar implementeert deze in plaats daarvan een parser.
Overeenkomen met een telefoonnummer
U kunt als volgt een prefixcode (a +
of (00) en vervolgens een nummer van 1 tot 1939 matchen met een optionele spatie):
Dit zoekt niet naar een geldig voorvoegsel maar naar iets dat mogelijk een voorvoegsel is. Bekijk de volledige lijst met voorvoegsels
(?:00|\+)?[0-9]{4}
Omdat de volledige lengte van het telefoonnummer maximaal 15 is, kunnen we maximaal 14 cijfers zoeken:
Voor het voorvoegsel wordt minstens 1 cijfer uitgegeven
[0-9]{1,14}
De getallen kunnen spaties, punten of streepjes bevatten en kunnen worden gegroepeerd op 2 of 3.
(?:[ .-][0-9]{3}){1,5}
Met het optionele voorvoegsel:
(?:(?:00|\+)?[0-9]{4})?(?:[ .-][0-9]{3}){1,5}
Als u wilt overeenkomen met een specifiek landformaat, kunt u deze zoekopdracht gebruiken en het land toevoegen, de vraag is zeker al gesteld.
Overeenkomen met een IP-adres
IPv4
Om te voldoen aan het IPv4-adresformaat, moet u controleren op nummers [0-9]{1,3}
drie keer {3}
gescheiden door punten \.
en eindigend met een ander nummer.
^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$
Deze reguliere expressie is te eenvoudig - als u wilt dat deze nauwkeurig is, moet u controleren of de getallen tussen 0
en 255
, waarbij de regex hierboven 444
in elke positie accepteert. U wilt 250-255 controleren met 25[0-5]
, of een andere 200-waarde 2[0-4][0-9]
, of een 100-waarde of minder met [01]?[0-9][0-9]
. U wilt controleren of deze wordt gevolgd door een punt \.
drie keer {3}
en vervolgens één keer zonder punt.
^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
IPv6
IPv6 adressen in de vorm van 8-bits 16 hex woorden gescheiden door de dubbele punt ( :
) teken. In dit geval controleren we op 7 woorden gevolgd door dubbele punten, gevolgd door een die dat niet is. Als een woord voorloopnullen heeft, kunnen deze worden afgekapt, wat betekent dat elk woord tussen 1 en 4 hexadecimale cijfers kan bevatten.
^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$
Dit is echter onvoldoende. Aangezien IPv6-adressen behoorlijk "woordachtig" kunnen worden, geeft de standaard aan dat alleen-nul woorden mogen worden vervangen door ::
Dit kan slechts eenmaal in een adres worden gedaan (voor ergens tussen 1 en 7 opeenvolgende woorden), omdat het anders onbepaald zou zijn. Dit levert een aantal (nogal vervelende) variaties op:
^::(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}$
^[0-9a-fA-F]{1,4}::(?:[0-9a-fA-F]{1,4}:){0,5}[0-9a-fA-F]{1,4}$
^[0-9a-fA-F]{1,4}:[0-9a-fA-F]{1,4}::(?:[0-9a-fA-F]{1,4}:){0,4}[0-9a-fA-F]{1,4}$
^(?:[0-9a-fA-F]{1,4}:){0,2}[0-9a-fA-F]{1,4}::(?:[0-9a-fA-F]{1,4}:){0,3}[0-9a-fA-F]{1,4}$
^(?:[0-9a-fA-F]{1,4}:){0,3}[0-9a-fA-F]{1,4}::(?:[0-9a-fA-F]{1,4}:){0,2}[0-9a-fA-F]{1,4}$
^(?:[0-9a-fA-F]{1,4}:){0,4}[0-9a-fA-F]{1,4}::(?:[0-9a-fA-F]{1,4}:)?[0-9a-fA-F]{1,4}$
^(?:[0-9a-fA-F]{1,4}:){0,5}[0-9a-fA-F]{1,4}::[0-9a-fA-F]{1,4}$
^(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}::$
Nu, alles bij elkaar opgeteld (met afwisseling) levert het volgende op:
^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|
^::(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}$|
^[0-9a-fA-F]{1,4}::(?:[0-9a-fA-F]{1,4}:){0,5}[0-9a-fA-F]{1,4}$|
^[0-9a-fA-F]{1,4}:[0-9a-fA-F]{1,4}::(?:[0-9a-fA-F]{1,4}:){0,4}[0-9a-fA-F]{1,4}$|
^(?:[0-9a-fA-F]{1,4}:){0,2}[0-9a-fA-F]{1,4}::(?:[0-9a-fA-F]{1,4}:){0,3}[0-9a-fA-F]{1,4}$|
^(?:[0-9a-fA-F]{1,4}:){0,3}[0-9a-fA-F]{1,4}::(?:[0-9a-fA-F]{1,4}:){0,2}[0-9a-fA-F]{1,4}$|
^(?:[0-9a-fA-F]{1,4}:){0,4}[0-9a-fA-F]{1,4}::(?:[0-9a-fA-F]{1,4}:)?[0-9a-fA-F]{1,4}$|
^(?:[0-9a-fA-F]{1,4}:){0,5}[0-9a-fA-F]{1,4}::[0-9a-fA-F]{1,4}$|
^(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}::$
Schrijf het op in multiline-modus en met een stapel opmerkingen, zodat degene die onvermijdelijk wordt belast met het uitzoeken van wat dit betekent niet achter je aan komt met een bot voorwerp.
Valideer een tijdreeks van 12 en 24 uur
Voor een 12-uurs tijdnotatie kan men gebruiken:
^(?:0?[0-9]|1[0-2])[-:][0-5][0-9]\s*[ap]m$
Waar
-
(?:0?[0-9]|1[0-2])
is het uur -
[-:]
is het scheidingsteken dat kan worden aangepast aan uw behoefte -
[0-5][0-9]
is de minuut -
\s*[ap]m
volgde een willekeurig aantal witruimte-tekens, enam
ofpm
Als u de seconden nodig hebt:
^(?:0?[0-9]|1[0-2])[-:][0-5][0-9][-:][0-5][0-9]\s*[ap]m$
Voor een 24-uursnotatie:
^(?:[01][0-9]|2[0-3])[-:h][0-5][0-9]$
Waar:
-
(?:[01][0-9]|2[0-3])
is het uur -
[-:h]
de afscheider, die kan worden aangepast aan uw behoefte -
[0-5][0-9]
is de minuut
Met de seconden:
^(?:[01][0-9]|2[0-3])[-:h][0-5][0-9][-:m][0-5][0-9]$
Waar [-:m]
een tweede scheidingsteken is, waarbij de h
urenlang wordt vervangen door een m
minuten en [0-5][0-9]
de seconde is.
Overeenkomen met Britse postcode
Regex overeenkomt met postcodes in het VK
De notatie is als volgt, waarbij A een letter en 9 een cijfer betekent:
Formaat | Dekking | Voorbeeld |
---|---|---|
Cel | Cel | |
AA9A 9AA | WC postcodegebied; EC1 – EC4, NW1W, SE1P, SW1 | EC1A 1BB |
A9A 9AA | E1W, N1C, N1P | W1A 0AX |
A9 9AA, A99 9AA | B, E, G, L, M, N, S, W | M1 1AE, B33 8TH |
AA9 9AA, AA99 9AA | Alle andere postcodes | CR2 6XH, DN55 1PT |
(GIR 0AA)|((([A-Z-[QVX]][0-9][0-9]?)|(([A-Z-[QVX]][A-Z-[IJZ]][0-9][0-9]?)|(([A-Z-[QVX]][0-9][A-HJKPSTUW])|([A-Z-[QVX]][A-Z-[IJZ]][0-9][ABEHMNPRVWXY])))) [0-9][A-Z-[CIKMOV]]{2})
Waar eerste deel:
(GIR 0AA)|((([A-Z-[QVX]][0-9][0-9]?)|(([A-Z-[QVX]][A-Z-[IJZ]][0-9][0-9]?)|(([A-Z-[QVX]][0-9][A-HJKPSTUW])|([A-Z-[QVX]][A-Z-[IJZ]][0-9][ABEHMNPRVWXY]))))
Tweede:
[0-9][A-Z-[CIKMOV]]{2})