CakeFest 2024: The Official CakePHP Conference

Classes de caractères

Un crochet ouvrant [ introduit une classe de caractères, et le crochet fermant ]la conclut. Le crochet fermant n'a pas de signification en lui-même. Si le crochet fermant est nécessaire à l'intérieur d'une classe de caractères, il faut qu'il soit le premier caractère (après un ^ éventuel) ou protégé avec un antislash.

Une classe de caractères remplace un seul caractère dans la chaîne sujet, à moins que le premier caractère de la classe soit un accent circonflexe ^, qui représente une négation : le caractère ne doit pas se trouver dans la classe. Si ^ est nécessaire dans la classe, il suffit qu'il ne soit pas le premier caractère, ou bien qu'il soit protégé par un antislash.

Par exemple, le caractère [aeiou] remplace n'importe quelle voyelle minuscule, tandis que [^aeiou] remplace n'importe quel caractère qui n'est pas une voyelle minuscule. ^ est une notation pratique pour spécifier des caractères qui sont dans une classe, en ne citant que ceux qui n'y sont pas. Le comportement est inchangé.

Avec l'option d'insensibilité à la casse, toutes les lettres d'une classe de caractères représentent en même temps la majuscule et la minuscule. Par exemple, [aeiou] représentera "A" ou "a", et [^aeiou] n'acceptera pas "A", tandis que sans l'option, elle l'accepterait.

Le caractère de nouvelle ligne n'est pas traité de manière spéciale dans les classes de caractères, quelque soit l'option PCRE_DOTALL ou PCRE_MULTILINE. Une classe telle que [^a] acceptera toujours une nouvelle ligne.

Le signe moins (-) est utilisé pour spécifier un intervalle de caractères, dans une classe. Par exemple, [d-m] remplace toutes les lettres entre d et m inclus. Si le caractère moins est requis dans une classe, il faut le protéger avec un antislash, ou le faire apparaître à une position où il ne pourra pas être interprété comme une indication d'intervalle, c'est-à-dire au début ou à la fin de la classe.

Il n'est pas possible d'avoir le caractère crochet fermant "]" comme fin d'intervalle. Un masque tel que [W-]46] est compris comme la classe de caractères contenant deux caractères ("W" et "-") suivie de la chaîne littérale "46]", ce qui fait qu'il va accepter "W46]" ou "-46]". Cependant, si "]" est protégé avec un antislash, le masque [W-\]46] est interprété comme une classe d'un seul caractère, contenant un intervalle de caractères. La valeur octale ou hexadécimale de "]" peut aussi être utilisée pour déterminer les limites de l'intervalle.

Les intervalles travaillent sur des séquences ASCII. Ils peuvent aussi être précisés avec des valeurs numériques : par exemple "[\000-\037]". Si cet intervalle inclut des lettres utilisées avec une option d'insensibilité de casse, les majuscules ou minuscules correspondantes seront aussi incluses. Par exemple, "[W-c]" est équivalent à "[][\^_`wxyzabc]", avec l'option d'insensibilité de casse. Si la table locale de caractères est "fr", "[\xc8-\xcb]" correspond aux caractères accentués.

Les types de caractères \d, \D, \S, \s, \w, \W peuvent aussi intervenir dans les classes de caractères. Par exemple, "[][\^_`wxyzabc][\dABCDEF]" acceptera n'importe quel caractère hexadécimal. Un accent circonflexe peut aussi être utilisé pour spécifier adroitement des ensembles de caractères plus restrictifs : par exemple [^\W_] accepte toutes les lettres et les chiffres, mais pas les soulignés.

Tous les caractères non alphanumériques autres que \, -, ^ (placés en début de chaîne) et ] n'ont pas de signification particulière, mais ils ne perdront rien à être protégés. Le délimiteur de motif est toujours spécial, et doit être protégé lorsqu'il est utilisé à l'intérieur d'une expression.

Perl supporte la notation POSIX pour les classes de caractères. Elles utilisent des noms entourés par [: et :]. PCRE supporte également cette notation. Par exemple, [01[:alpha:]%] trouve "0", "1", toute lettre, ou encore le caractère "%". Les noms de classe supportés sont :

Classes de caractères
alnum lettres et chiffres
alpha lettres
ascii codes caractères 0 - 127
blank espace ou tabulation uniquement
cntrl caractères de contrôle
digit chiffres décimaux (identique à \d)
graph caractères d'impression, excluant les espaces
lower lettres en minuscule
print caractères d'impression, incluant les espaces
punct caractères d'impression, excluant les lettres et les chiffres
space espace blanc (pas tout à fait identique à \s)
upper lettres en majuscule
word caractères composant un mot (identique à \w)
xdigit chiffres hexadécimaux
Les caractères d'espacement (space) sont HT (9), LF (10), VT (11), FF (12), CR (13), et l'espace (32). Notez que cette liste inclut le caractère VT (code 11). Ceci rend la classe "space" différente de \s, qui n'inclut pas ce caractère VT (pour une raison de compatibilité Perl).

La classe word est une extension Perl, et blank est une extension GNU de Perl 5.8. La négation est une autre extension Perl ; elle est indiquée par le caractère ^ après un double-point. Par exemple, [12[:^digit:]] trouve "1", "2", mais aussi tout caractère qui n'est pas un chiffre.

En mode UTF-8, les caractères dont les valeurs sont supérieures à 128 ne seront trouvés par aucune des classes de caractères POSIX. À partir de libpcre 8.10 certains caractères de classes ont été modifié pour utiliser des caractères de propriétés Unicode, dans ce cas les restrictions mentionnées ne s'applique pas. Référez-vous au » manuel PCRE(3) pour plus de détails.

Les propriétés des caractères Unicode peuvent apparaitre à l'intérieur d'une classe de caractère. Ils ne peuvent pas faire partie d'une étendue. Le caractère moins (tiret) après une classe de caractère Unicode satisfera littéralement. Essayer de terminer une étendue avec une propriété de caractère Unicode résultera en un avertissement.

add a note

User Contributed Notes 4 notes

up
19
greaties at ghvernuft dot nl
2 years ago
From deep down the PCRE manual at http://www.pcre.org/pcre.txt :

\d any decimal digit
\D any character that is not a decimal digit
\h any horizontal white space character
\H any character that is not a horizontal white space character
\s any white space character
\S any character that is not a white space character
\v any vertical white space character
\V any character that is not a vertical white space character
\w any "word" character
\W any "non-word" character
up
3
Julian
1 year ago
Examples with Character classes

<?php

$stringA
= "1 In the beginning God created the heavens and the earth.";
$stringB = preg_replace('/[[:^alnum:]]/', '', $stringA); // string(46) "1InthebeginningGodcreatedtheheavensandtheearth"
$stringC = preg_replace('/[[:^alpha:]]/', '', $stringA); // string(45) "InthebeginningGodcreatedtheheavensandtheearth"
$stringD = preg_replace('/[[:^ascii:]]/', '', "Pokémon"); // string(6) "Pokmon"
$stringE = preg_replace('/[[:^blank:]]/', '*', $stringA); // string(57) "* ** *** ********* *** ******* *** ******* *** *** ******"
$stringF = preg_replace('/[[:blank:]]/', '-', $stringA); // string(57) "1-In-the-beginning-God-created-the-heavens-and-the-earth."

$stringG = sprintf("Vertical Tabulation: %s", chr(11)); // string(22) "Vertical Tabulation: "
$stringH = preg_replace('/[[:cntrl:]]/', '', $stringG); // string(21) "Vertical Tabulation: "
$stringLengthG = strlen($stringG); // int(22)
$stringLengthH = strlen($stringH); // int(21)

$stringI = preg_replace('/[[:digit:]]/', '', 'My age is 35'); //string(10) "My age is "
$stringJ = preg_replace('/[[:^digit:]]/', '', 'My age is 35'); // string(2) "35"

$stringK = preg_replace('/[[:^graph:]]/', '', $stringG); // string(19) "VerticalTabulation:"
$stringL = preg_replace('/[[:graph:]]/', '', $stringG); // string(3) " "

$stringM = preg_replace('/[[:lower:]]/', '', $stringG); // string(6) "V T: "
$stringN = preg_replace('/[[:^lower:]]/', '', $stringG); // string(16) "erticalabulation"

$stringO = preg_replace('/[[:^print:]]/', '', $stringG); // string(21) "Vertical Tabulation: "
$stringP = preg_replace('/[[:print:]]/', '', $stringG); // string(1) " "

$stringQ = preg_replace('/[[:punct:]]/', '', $stringG); // string(21) "Vertical Tabulation "
$stringR = preg_replace('/[[:^punct:]]/', '', $stringG); // string(1) ":"

$stringS = preg_replace('/[[:space:]]/', '', $stringG); // string(19) "VerticalTabulation:"
$stringT = preg_replace('/[[:^space:]]/', '', $stringG); // string(3) " "

$stringU = preg_replace('/[[:upper:]]/', '', $stringG); // string(20) "ertical abulation: "
$stringV = preg_replace('/[[:^upper:]]/', '', $stringG); // string(2) "VT"

$stringW = preg_replace('/[[:word:]]/', '', $stringG); // string(4) " : "
$stringX = preg_replace('/[[:^word:]]/', '', $stringG); // string(18) "VerticalTabulation"

$stringY = preg_replace('/[[:xdigit:]]/', '', 'abcdefghijklmnopqrstuvwxyz0123456789'); // string(20) "ghijklmnopqrstuvwxyz"
$stringZ = preg_replace('/[[:^xdigit:]]/', '', 'abcdefghijklmnopqrstuvwxyz0123456789'); // string(16) "abcdef0123456789"
up
6
wordragon at wrestingcontrol dot com
5 years ago
The documentation says:

"The character types \d, \D, \s, \S, \w, and \W may also appear in a character class, and add the characters that they match to the class."

It does not stress that other escape types may not. I wanted to split a string on either a comma (","), or a new line "\n". When my input stream began to include "\r\n", I decided to change "\n" to "\R". Unfortunately, my test string did not include a capital "R", or I might have found the problem sooner. My '/[\R,]/' was simply splitting on comma and the letter "R".

My test string...
"The Yum-Yum Company\r\n127 bernard street"

What DID work: '/(?:\R|,)+/'

["The Yum-Yum Company","127 bernard street"]

Given character classes only match one character, I can see clearly why my expectations were justifiably dashed, but hopefully this comment will save time for someone else.

I might add, this has taught me the value of PCRE_EXTRA (modifier "X"), which I have begun to use routinely now.
up
-8
php at delegated dot net
5 years ago
Some characters may not work as expected within a custom class. MS double quote for example is unrecognised when included in a class but is recognised otherwise.

ie:
<?php
preg_match_all
('/<a href=("|“)/')
?> will match but
<?php
preg_match_all
('/<a href=["“]/')
?> will not
when applied to <a href=“path">
To Top