OVH Cloud OVH Cloud

regexp simple qui ne marche pas...

19 réponses
Avatar
CrazyCat
Bonjour à tous...

J'essaye de faire une regexp très simple qui permet de formatter
proprement un numéro de télephone, c'est à dire:
mon téléphone est stocké sous forme de chaine, par exemple "0123456789"
Pour l'affichage, je veux mettre "01.23.45.67.89"

Voila ce que je fait:
function tel_sql_php($sql_tel) {
$pattern = "([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})";
if (eregi($pattern, $sql_tel, $myregs)) {
$php_tel =
$myregs[1].".".$myregs[2].".".$myregs[3].".".$myregs[4].".".$myregs[5];
return $php_tel;
}
}

Ceci fonctionne, mais sitot que j'utilise des caractères plus propres,
c'est à dire que j'utilise:
$pattern = "(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})";
ça ne marche plus, le eregi ne match pas.

Quelqu'un peut il me dire ce que je rate?

Merci bien
--
Humour: http://www.chatfou.com
Tchattez en liberté: http://www.c-p-f.net
Tout sur les eggdrops: http://www.c-p-f.org

10 réponses

1 2
Avatar
Daedalus
La raison en est simple. Les deux expression (d{2}) et ([d]{2}) ou
([0-9]{2}) ne sont absoluement pas équivalente. [d] et [0-9] sont des
classe de caractères qui corespondent à des chiffres, alors que d est un
chiffre. Plus clairement, [d]{2} veut dire 2 chiffres, alors que d{2} veut
dire 1 chiffre 2 fois de suite (par exemple "22" mais pas "12" ou "53".

Ceci dit, il serait plus simple je crois d'utiliser *reg_replace et tout
faire en un coup. Exemple avec preg_replace ( désolé je n'utilise jamais
ereg ).
<?
// ...
$pattern = "/([d]{2})([d]{2})([d]{2})([d]{2})([d]{2})/";
$php_tel = preg_replace($pattern, "$1.$2.$3.$4.$5", $sql_tel);
//...
?>

Dae


Bonjour à tous...

J'essaye de faire une regexp très simple qui permet de formatter
proprement un numéro de télephone, c'est à dire:
mon téléphone est stocké sous forme de chaine, par exemple "0123456789"
Pour l'affichage, je veux mettre "01.23.45.67.89"

Voila ce que je fait:
function tel_sql_php($sql_tel) {
$pattern = "([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})";
if (eregi($pattern, $sql_tel, $myregs)) {
$php_tel > $myregs[1].".".$myregs[2].".".$myregs[3].".".$myregs[4].".".$myregs[5];
return $php_tel;
}
}

Ceci fonctionne, mais sitot que j'utilise des caractères plus propres,
c'est à dire que j'utilise:
$pattern = "(d{2})(d{2})(d{2})(d{2})(d{2})";
ça ne marche plus, le eregi ne match pas.

Quelqu'un peut il me dire ce que je rate?

Merci bien
--
Humour: http://www.chatfou.com
Tchattez en liberté: http://www.c-p-f.net
Tout sur les eggdrops: http://www.c-p-f.org


Avatar
Daedalus
Ignorez ma réponse précédente... après vérification avec preg_*, d{2} et
[d]{2} devrait donner le même résultat. Je ne sais pourquoi mais j'avais
l'impression que d{2} se traduisait par 2 fois le même nombre, mais non. Et
je ne peux même pas me tirer d'embarras en prétendant que c'est le cas en
perl, car ça n'est pas vrai... Je me suis gourré :-).

Ceci dit, l'exemple donné précédement fonctionne toujours (et fonctionnerait
aussi sans les []).
Je ne suis pas vraiment famillier avec les fonctions ereg, mais êtes vous
certain que les classe du genre d w etc. fonctionne avec ereg ? Ma
solution, qui n'en est pas tout à fait une, utiliser les fonctions preg_*,
même le manuel le recommende indirectement en notant que preg_* est une
alternative plus rapide à ereg.

Désolé
Dae
Avatar
laurent vilday
CrazyCat Wednesday 29 December 2004 13:05
<cqu1q4$nku$

J'essaye de faire une regexp très simple qui permet de formatter
"0123456789" Pour l'affichage, je veux mettre "01.23.45.67.89"

function tel_sql_php($sql_tel) {
$pattern = "([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})";
if (eregi($pattern, $sql_tel, $myregs)) {

Ceci fonctionne, mais sitot que j'utilise des caractères plus
propres, c'est à dire que j'utilise:
$pattern = "(d{2})(d{2})(d{2})(d{2})(d{2})";
ça ne marche plus, le eregi ne match pas.


ereg et eregi utilisent des expressions POSIX donc les chiffres ce
serait plutot [:digit:]
http://fr.php.net/manual/fr/ref.regex.php
http://www.tin.org/bin/man.cgi?section=7&topic=regex

d c'est une expression PCRE (toutes les joyeuses fonctions preg)
http://fr.php.net/manual/fr/ref.pcre.php

pourquoi utiliser eregi (case insensitive) si tu veux match des
chiffres ?

--
laurent
http://mokhet.com/

Avatar
CrazyCat
Merci aussi à Daedalus...

laurent vilday wrote:
ereg et eregi utilisent des expressions POSIX donc les chiffres ce
serait plutot [:digit:]
http://fr.php.net/manual/fr/ref.regex.php
http://www.tin.org/bin/man.cgi?section=7&topic=regex
d c'est une expression PCRE (toutes les joyeuses fonctions preg)
http://fr.php.net/manual/fr/ref.pcre.php


ok merci... en fait j'ai l'habitude des regexp en ASP et en TCL, pas du
tout en php... Ayant vu ereg (et ses copains), je n'ai pas cherché plus
loin sur le preg (je fais du php, pas du perl :))

pourquoi utiliser eregi (case insensitive) si tu veux match des
chiffres ?


vieille habitude (très mauvaise) que j'ai, comme faire un grep -ri
quelque soit ce que je cherche.

Merci à vous deux et je note bien qu'une regexp "normalisée" (c'est à
dire ala perl) fonctionne avec preg.


--
Humour: http://www.chatfou.com
Tchattez en liberté: http://www.c-p-f.net
Tout sur les eggdrops: http://www.c-p-f.org

Avatar
nospam
Daedalus wrote:

La raison en est simple. Les deux expression (d{2}) et ([d]{2}) ou
([0-9]{2}) ne sont absoluement pas équivalente. [d] et [0-9] sont des
classe de caractères qui corespondent à des chiffres, alors que d est un
chiffre. Plus clairement, [d]{2} veut dire 2 chiffres, alors que d{2} veut
dire 1 chiffre 2 fois de suite (par exemple "22" mais pas "12" ou "53".


Mmmh ... tu es sur ?
Je viens de tester avec preg_match() et les deux ont l'air équivalents,
d{2} matche bien '12' par exemple.

Testé avec les regex Ruby également.

--
Romuald Brunet, ICQ 33033393, http://mog.online.fr

Remplacez nospam par mon prénom pour me contacter par email

Avatar
John Gallet
'alut,


Voila ce que je fait:
function tel_sql_php($sql_tel) {
$pattern = "([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})";
if (eregi($pattern, $sql_tel, $myregs)) {
$php_tel =
$myregs[1].".".$myregs[2].".".$myregs[3].".".$myregs[4].".".$myregs[5];
return $php_tel;
}
}


Tu fais comme tu le sens, mais moi je considère que c'est le cas typique
du code inutilement compliqué. Dans 6 mois quand tu le reliras ou que tu
chercheras un bug, tu ne comprendras plus rien. Il suffit de faire 5
substrings sur taille fixe, c'est beaucoup plus lisible et couvre
exactement le même nombre de cas. Si tu veux gérer les numéros sous la
forme +(33)12345678 tu commences tes substrings à l'indice du ) et non à
l'indice zéro.

a++
JG

PS : on est bien d'accord : rien qu'un bon commetaire ne saurait
éclaircir, mais je ne vois pas l'intérêt de sortir une regexp pour ça.

Avatar
Daedalus
Oui je sais, je dois avoir eu une hallucination ;-).
J'ai posté une rectification à ce message débutant par "Ignorez ma réponse
précédente... "

Encore désolé

Mmmh ... tu es sur ?
Je viens de tester avec preg_match() et les deux ont l'air équivalents,
d{2} matche bien '12' par exemple.

Testé avec les regex Ruby également.

--
Romuald Brunet, ICQ 33033393, http://mog.online.fr

Remplacez nospam par mon prénom pour me contacter par email


Avatar
CrazyCat
Romuald Brunet wrote:
Je viens de tester avec preg_match() et les deux ont l'air équivalents,
d{2} matche bien '12' par exemple.
Testé avec les regex Ruby également.


Je confirme que d{2} est l'équivalent de [0-9]{2}.
Je pense que Daedalus a confondu avec d+ qui serait effectivement la
répétition du caractère précédent (pas testé).
En ce qui concerne l'usage ou pas de [ ], ça dépend de l'expression.

Une image simple serait de dire que quoi qu'il arrive, "[1 + 2] == 1 +
2" donc les [] sont facultatifs, mais "[1 + 2] * 3 != 1 + 2 * 3" donc il
faut les mettre pour avoir le résultat escompté.


--
Humour: http://www.chatfou.com
Tchattez en liberté: http://www.c-p-f.net
Tout sur les eggdrops: http://www.c-p-f.org

Avatar
CrazyCat
John Gallet wrote:
Tu fais comme tu le sens, mais moi je considère que c'est le cas typique
du code inutilement compliqué. Dans 6 mois quand tu le reliras ou que tu
chercheras un bug, tu ne comprendras plus rien. Il suffit de faire 5
substrings sur taille fixe, c'est beaucoup plus lisible et couvre
exactement le même nombre de cas. Si tu veux gérer les numéros sous la
forme +(33)12345678 tu commences tes substrings à l'indice du ) et non à
l'indice zéro.


Oui, c'est bien plus simple mais...

PS : on est bien d'accord : rien qu'un bon commetaire ne saurait
éclaircir, mais je ne vois pas l'intérêt de sortir une regexp pour ça.


Ce que j'ai donné n'est qu'une partie de la fonction, que j'ai mis ainsi
pour montrer ce qui me posait soucis dans la regexp.
En fait, cet exemple me permet de mettre les différents composants dont
je n'était pas sûr (la pattern et les fonctions de regexp).
Je ne suis pas encore fou au point de faire des regexp pour le plaisir :)

--
Humour: http://www.chatfou.com
Tchattez en liberté: http://www.c-p-f.net
Tout sur les eggdrops: http://www.c-p-f.org

Avatar
Vincent Lascaux
function tel_sql_php($sql_tel) {
$pattern = "([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})";
if (eregi($pattern, $sql_tel, $myregs)) {
$php_tel =
$myregs[1].".".$myregs[2].".".$myregs[3].".".$myregs[4].".".$myregs[5];
return $php_tel;
}
}


Tu fais comme tu le sens, mais moi je considère que c'est le cas typique
du code inutilement compliqué. Dans 6 mois quand tu le reliras ou que tu
chercheras un bug, tu ne comprendras plus rien. Il suffit de faire 5
substrings sur taille fixe, c'est beaucoup plus lisible et couvre
exactement le même nombre de cas.


Pas d'accord :
- D'abord, son pattern va extraire le premier numéro de telephone trouvé. Je
sais pas si c'est le but (le nom de la variable $sql_tel suggère que non),
mais en tous cas, ta solution ne remplit pas le même contrat.
- Il faut aussi faire 5 is_numeric pour vérifier que les résultats des
substrings sont bien des nombres
- La solution peut être facilement modifiée pour permettre des choses plus
complexes. Par exemple
$pattern = "([0-9]{2})[ -.]*([0-9]{2})[ -.]*([0-9]{2})[ -.]*([0-9]{2})"
permet de gérer des numéros de tel formattés avec des espaces, des tirets ou
des points entre les groupements de deux nombres. Ca devient vite un
cauchemard avec des substring et des strpos.

La solution pour pouvoir se relire dans 6 mois c'est pas de se tourner vers
un code plus simple et moins adapté, mais de commenter.

Si tu veux gérer les numéros sous la forme +(33)12345678 tu commences tes
substrings à l'indice du ) et non à l'indice zéro.


Ou tu rajoutes (+([0-9]{1,2}))? au début du pattern... ce qui a l'avantage
de ne pas interpréter comme numero de téléphone n'importe quoi qui contient
une parenthèse fermante et une suite de nombres.

--
Vincent


1 2