Een vraagje ... is het mogelijk (en zo ja hoe) om via een regex dubbele tekens af te keuren?
Wat ik graag zou willen is dat ik bijv. kan aangeven dat er letters en cijfers gebruikt mogen worden, en spaties, punten en streepjes. Dan krijg je zoiets:
pattern="^[- .0-9A-Za-z]$"
Maar ik wil niet dat men dubbele spaties, streepjes en punten kan gebruiken.
Dus dit mag wel: Ozzie.PHP-Hulp
Maar dit niet: Ozzie..PHP--Hulp
Is het mogelijk om in een regex aan te geven dat er alleen 'enkele' streepjes, spaties en punten gebruikt mogen worden?
Ik geloof dat jullie me verkeerd begrepen hebben :-s
De vraag is hoe ik dus een negatieve match krijg. Er hoeft niks vervangen te worden. De regex moet simpelweg niet slagen als er .. of -- of dubbele spatie in staat.
Ik denk dat ik het maar ga oplossen met lookaheads.
Toevoeging op 26/12/2016 21:27:04:
PS
>> Wel, Ozzie heeft vastwel een 'goed basisboek' waar het in staat hoe je het doet.
foreach ($tests as $t) {
if (preg_match($pattern, $t)) {
echo 'OK '.$t.PHP_EOL;
} else {
echo 'NO '.$t.PHP_EOL;
}
}
?>
Dit staat bijv. "Ozzie.-PHP-Hulp" wel toe, als dat ook niet mag wordt de pattern:
<?php
$pattern = '/
^
(?:
[[:alnum:]] # letters + cijfers
|
(?:
[.\s-] # punt, spatie en streepje
(?:[^.\s-]|$) # gevolgt door of een *niet* punt, spatie, streepje of het einde van de string
)
)+
$
/x';
?>
Dit stukje ?:[[:alnum:]] werkt bij mij alleen als ik het zo doe
?:[0-9A-Za-z]
Dus zonder die dubbele blokhaken. Heb je toevallig enig idee waarom? Ook zie ik geen verschil als ik in dit stukje ?: weglaat. Het resultaat lijkt dan gewoon hetzelfde te zijn.
(PS ik gebruik het als een pattern in een html5 input-veld)
(PS ik gebruik het als een pattern in een html5 input-veld)
Dat verklaard het [[:alnum:]] stukje :) HTML5 input velden gebruiken de JavaScript regex engine. Deze ondersteund geen speciale character classes zoals [:alnum:] (wat gewoon een short-hand is voor [\w\d] in PHP).
Wat doet nu precies die "?:" ?
Normaal gesproken wordt een capture group "gecaptured" (opgeslagen). Dit betekend dat we er later weer naar kunnen referreren doormiddel van zijn index. Bijvoorbeeld:
preg_match('/(a)(b)(c)/', 'abc');
/* Capture groups:
1: a
2: b
3: c */
Deze indexen kun je dan weer gebruiken in de regex. Bijvoorbeeld /([a-z])\1/ zal 2 keer dezelfde letter achter elkaar matchen.
Dit opslaan van de capture group kost wat geheugen en wat tijd. Door (?:...) ipv (...) te gebruiken vertel je dat de capture group niet opgeslagen moet worden. Op deze manier wordt je regex iets sneller. Dit is waarschijnlijk vooral pas merkbaar bij grote hoeveelheden matchen, dus in dit geval een grote lengte van de string.
Ah zo ... dan kan ik dus beter overal die ?: toepassen. Weer wat geleerd :-)
Nog een laatste vraag.
Nog even uitgaande van die voorgaande regex ...
Dit stukje (?:[^.\s-]|$) vond ik op zich wel mooi ... dat je dus ook niet bijv. .- kunt krijgen. Het nadeel is nu echter dat je ipv .- wel bijv. een vreemd teken kunt zetten bijv .* wat ik eigenlijk niet wil. Is dat nog (makkelijk) op te lossen?
Idealiter zou ik (ongeveer) dit willen:
BEGIN en EINDIG de string met een letter of getal. Daartussen zijn de enige toegestane karakters letters en cijfers en de volgende vreemde tekens: spatie streepje punt ... maar die mogen niet na elkaar volgen, met als enige uitzondering een punt die wél gevolgd mag worden door een spatie. Heb je daar nog een tip voor hoe ik dat moet aanpakken?
Dit mag:
Ozzie PHPhulp
Ozzie.PHP-hulp
Ozzie. PHP-hulp
Maar dit mag niet:
.Ozzie (begint niet met een letter of getal)
Ozzie- (eindigt niet met een letter of getal)
Ozzie.-PHPhulp (punt en streepje na elkaar mag niet)