
Envoyé par
Obsidian
Plus précisément, c'est le marqueur de début d'expression (l'extrémité gauche), à condition d'être le premier caractère de l'expression. Sinon il est traité comme un caractère ordinaire.
De la même façon, « $ » est le marqueur de fin de chaîne, à condition d'être le dernier caractère de l'expression.
Attention! ^ marque le début de la chaîne sujet et il peut-être placé n'importe où dans la pattern. En aucun cas il est traité comme un caractère ordinaire, et ce, même s'il n'est pas placé au début. Donc pour figurer le caractère littéral ^ dans une pattern, il doit être échappé \^.
Cas particulier des classes de caractères: dans une classe de caractères, ^ est utilisé pour figurer la négation de la classe s'il est placé au début de la classe (exemple: [^0-9] tout ce qui n'est pas le rang de 0 à 9). Lorsqu'il n'est pas en première position dans une classe, alors là oui, il n'a plus de signification spéciale (exemple: [0-9^] le rang de 0 à 9 ou un accent circonflexe). Donc si on veut absolument le placer en première position dans la classe, on doit l'échapper d'un antislash, et ce, même s'il définit le début d'un rang (exemples: [^-a] tout ce qui n'est pas un tiret et la lettre minuscule "a", alors que [\^-a] le rang allant de ^ à a, soient les caractères ^, _, ` et a ).
$ marque la fin de chaîne mais il est ambiguë car ce n'est pas toujours le cas. Il marque aussi la fin de la dernière ligne de la chaîne, si celle-ci est suivie d'un saut de ligne avant la fin de la chaîne, exemple:
1 2
| echo preg_match('~abcd$~', 'abcd'); // 1 ok, rien d'étonnant
echo preg_match('~abcd$~', "abcd\n"); // 1 on est pourtant pas à la fin de la chaîne |
Pour lever l'ambiguïté de $, il faut ajouter le modificateur global D qui correspond à l'option PCRE2_DOLLAR_ENDONLY. Ainsi on obtient bien le resultat escompté:
echo preg_match('~abcd$~D', "abcd\n"); // 0
Pour ma part, je préfère utiliser le couple \A \z (A majuscule et z minuscule) pour figurer le début et la fin de chaîne, car ils n'y a pas l'ambiguïté pré-citée et leur signification ne change pas avec le modificateur m.
Sinon en partant de la pattern de départ, disons ~^[0-9]+-~, on peut ajouter des alternatives séparées pour gérer les autres cas:
1 2 3
| echo preg_replace('~^[0-9]+-|-[0-9]+(?:\.html)?$|\.html$~D', '', $str);
// ou encore
echo preg_replace('~\A[0-9]+-|-[0-9]+(?:\.html)?\z|\.html\z~', '', $str); |
De cette manière, pas besoin de capturer, on se contente d'éliminer.
Partager