Par simple curiosité, j'essaie de déterminer quel est le bon moyen d'échapper à une barre oblique inversée pour l'utiliser dans un modèle d'expression régulière PHP comme suit:
TEST 01: (3 anti-slash)
$pattern = "/^[\\\]{1,}$/";
$string = '\\';
// ----- RETURNS A MATCH -----
TEST 02: (4 anti-slash)
$pattern = "/^[\\\\]{1,}$/";
$string = '\\';
// ----- ALSO RETURNS A MATCH -----
Selon les articles ci-dessous, 4 est censé être la bonne façon, mais ce qui me dérange, c'est que les deux tests ont donné une correspondance. Si les deux ont raison, alors 4 est-il le moyen préféré?
RESSOURCES:
Le fait est que vous utilisez une classe de caractères, []
, de sorte que le nombre de barres obliques inverses littérales incorporées dans celle-ci importe peu, elle sera traitée comme une seule barre oblique inversée.
par exemple. les deux expressions rationnelles suivantes:
/[a]/
/[aa]/
sont à toutes fins utiles identiques en ce qui concerne le moteur de regex. Les classes de caractères prennent une liste de caractères et les "réduisent" pour les faire correspondre à un seul caractère, le long des lignes de "pour le caractère actuel considéré, s'agit-il de l'un des caractères listés dans le []
?". Si vous énumérez deux barres obliques inverses dans la classe, alors ce sera "le caractère est-il une barre oblique ou est-ce une barre oblique inversée?".
// PHP 5.4.1
// Either three or four \ can be used to match a '\'.
echo preg_match( '/\\\/', '\\' ); // 1
echo preg_match( '/\\\\/', '\\' ); // 1
// Match two backslashes `\\`.
echo preg_match( '/\\\\\\/', '\\\\' ); // Warning: No ending delimiter '/' found
echo preg_match( '/\\\\\\\/', '\\\\' ); // 1
echo preg_match( '/\\\\\\\\/', '\\\\' ); // 1
// Match one backslash using a character class.
echo preg_match( '/[\\]/', '\\' ); // 0
echo preg_match( '/[\\\]/', '\\' ); // 1
echo preg_match( '/[\\\\]/', '\\' ); // 1
Lorsque vous utilisez trois barres obliques inverses pour faire correspondre un '\'
, le modèle ci-dessous est interprété comme correspondant à un '\'
suivi d'un 's'
.
echo preg_match( '/\\\\s/', '\\ ' ); // 0
echo preg_match( '/\\\\s/', '\\s' ); // 1
Lorsque vous utilisez quatre barres obliques inverses pour faire correspondre un '\'
, le modèle ci-dessous est interprété comme correspondant à un '\'
suivi d'un caractère d'espacement.
echo preg_match( '/\\\\\s/', '\\ ' ); // 1
echo preg_match( '/\\\\\s/', '\\s' ); // 0
La même chose s'applique si à l'intérieur d'une classe de personnage.
echo preg_match( '/[\\\\s]/', ' ' ); // 0
echo preg_match( '/[\\\\\s]/', ' ' ); // 1
_ {Aucun des résultats ci-dessus n'est affecté par la présence de chaînes entre guillemets au lieu de guillemets simples.
Conclusions:
Que ce soit à l'intérieur ou à l'extérieur d'une classe de caractères entre crochets, une barre oblique inverse littérale peut être associée à l'aide de trois barres obliques inverses uniquement '\\\'
, sauf si le caractère suivant du modèle est également inversé, auquel cas la barre oblique inversée littérale doit être associée à quatre barres obliques inverses.
Recommandation:
Utilisez toujours quatre barres obliques inverses '\\\\'
dans un motif regex lorsque vous cherchez à faire correspondre une barre oblique inversée.
Pour éviter ce genre de code peu clair, vous pouvez utiliser\x5c Comme ça :)
echo preg_replace( '/\x5c\w+\.php$/i', '<b>${0}</b>', __FILE__ );
J'ai étudié cela il y a des années. En effet, la première barre oblique inverse échappe à la deuxième et ils forment ensemble un caractère «vrai baclkslash» et ce vrai masque échappe au troisième. Donc, comme par magie, 3 barres obliques inversées fonctionnent.
Toutefois, il est conseillé d'utiliser 4 barres obliques inverses au lieu des 3 barres obliques inverses ambiguës.
Si je me trompe à propos de quelque chose, n'hésitez pas à me corriger.
Vous pouvez également utiliser les éléments suivants
$regexp = <<<EOR
schemaLocation\s*=\s*["'](.*?)["']
EOR;
preg_match_all("/".$regexp."/", $xml, $matches);
print_r($matches);
mots-clés: dochere, nowdoc