Regex et prise de tête !

Regex et prise de tête ! - PHP - Programmation

Marsh Posté le 03-10-2011 à 22:56:08    

Bonjour  
 
J'utilise l'expression suivante dans la class de mon moteur de recherche pour afficher  les 15 mots précédents et suivants le mot clé ($cles) tappé par mes visiteurs :
 
preg_match_all(sprintf('`(\b(?:[^\s]+\s){0,15}%s(?:\s[^\s]+){0,15}\b)`i', $cles), html_entity_decode(strip_tags($row[7])), $matches, PREG_SET_ORDER);
$tab[$compteur][7]= preg_replace('#'.$cles.'#i', '<span style="background:#FF3">'.$cles.'</span>', $matches[0][0]);
 
Mon problème est que lorsque mes visiteurs tappent un mot qui est inclus dans un mot de ma BDD (exemple : ils tappent 'voiture' et dans la base j'ai 'voitures'), je n'ai aucun résultat à l'affichage ... De même si mes visiteurs tappent ''voiture' et que dans ma base le mot est suivi d'une virgule ou d'une parenthèse ou que n'importe quel caractère entoure le mot sans espace.
 
Avez-vous des idées pour corriger mon problème ?


Message édité par inspecteurmota le 04-10-2011 à 11:38:10
Reply

Marsh Posté le 03-10-2011 à 22:56:08   

Reply

Marsh Posté le 04-10-2011 à 11:42:07    

En fait j'ai changé mon regex par celui là :
 
$masque = ('/  \b (.{0,75}?) \b \s*? \b ( [\S]* '.$cles.' [\S]* ) \b \s*? \b ((.?[^'.$cles.'?].?).{0,75})  \b /ix');
preg_match_all($masque, html_entity_decode(strip_tags($row[7])), $matches, PREG_SET_ORDER);
$tab[$compteur][7]= preg_replace('#'.$cles.'#i', '<span style="background:#FF3">'.$cles.'</span>', $matches[0][0]);
 
Du coup il attrape les 75 caractères précédents et suivant le mot clé mais ça déconne toujours si le mot est suivi d'un point et d'un saut de ligne (forcément vu l'utilisation du . dans le regex).
 
Qqun a-t-il une idée ?

Reply

Marsh Posté le 05-10-2011 à 10:07:47    

Ta regexp ne m'inspire pas trop, mais je remarque :
1] des espaces inutiles
2] des crochets inutiles autour du \s* et des \b et des ? qu'on se demande à quoi ils servent
3] qu'en fin de ton premier $cles, tu n'offres pas la possibilité de caractères additionnels avec un .*


---------------
Directeur Technique (CTO)
Reply

Marsh Posté le 05-10-2011 à 10:19:05    

Essaye un truc du genre :
 
$regex = '/(.+)('.$searchedWord.')(.+)/Usi';
 
Sinon si c'est juste un highlight que tu veux faire, un simple strtr suffit :
 
$highlightedString = strtr($string, array($searchedWord => '<span class=highlight>'.$searchedWord.'</span>'));
 
A noter que les deux exemples acceptent des tableaux, si tu as besoin d'effectuer des remplacements multiples...


---------------
Directeur Technique (CTO)
Reply

Marsh Posté le 05-10-2011 à 11:47:07    

Merci de ta réponse
J'ai testé ton regex mais ça ne fonctionne absolument pas d'autant que le nombre de caractères/mots à afficher n'y apparait pas
1/ les espaces sont inutiles mais ça me permet juste de mieux lire la regex
2/ pour les crochets je vois pas trop de quoi tu parles, il n'y en a pas autour du \s* ni des \b
3/ la regex accepte bien les caractères précédents ou suivants le mot recherché même sans .*
Quant au highlight le mien fonctionne bien aussi (il est indépendant de l'opération avec le regex et s'éxécute après)
 
En fait mon regex fonctionne dans 90% des cas sauf quand il y a un saut de ligne dans le coin

Reply

Marsh Posté le 05-10-2011 à 16:42:22    

Et le \s*? ... Il te sert à quoi exactement ?
 
Parce que ? C'est pour dire de 0 à 1, or comme tu as mis une étoile devant, ça sert à rien.
 
0 ou 1 fois un truc répété de 0 à N fois, ça revient à mettre une restriction
De Max(0x0, 0x1) à Max(0xN, 1xN)
De Max(0, 0) à Max(0, N)
De 0 à N
 
Donc la condition précédente du *
 
Je t'assure que ta regex est faussement compliquée pour ton problème...
 
Au passage, tes espaces ne comptent pas pour du beurre, ils sont évalués !


---------------
Directeur Technique (CTO)
Reply

Marsh Posté le 05-10-2011 à 16:49:56    

Ton problème vient de ta clause de négation. Le motif dans les crochets n'est pas un mot, mais un caractère unique, ayant pour valeur une des lettres constituant $cles
 
Donc si ta chaine de caractère jouant le role de texte présente le mot cles suivit d'un caractère constituant $cles, la regexp ne matche pas (elle ne matche que pour les autres caractères.


---------------
Directeur Technique (CTO)
Reply

Marsh Posté le 06-10-2011 à 11:41:47    

CyberDenix a écrit :

Et le \s*? ... Il te sert à quoi exactement ?


A faire un pattern qui n'est pas gourmand.
Bon, dans ce cas il est inutile, mais par exemple un pattern /.*?plop/ appliqué à la chaîne "Lorem ipsum plop dolor sit amet plop" s'arrêtera au premier plop alors que /.*plop/ ne s'arrêtera qu'au dernier.


---------------
Main/Alt1/Alt2/Alt3
Reply

Marsh Posté le 06-10-2011 à 19:39:50    

Donc en fait le U rend toute l'expression greedy et le ? le ferait au cas par cas ?


---------------
Directeur Technique (CTO)
Reply

Marsh Posté le 07-10-2011 à 15:33:53    

En gros : si l'expression est greedy (cas par défaut) le ? donne un comportement ungreedy à * et +. Par contre, si l'expression est ungreedy (modifieur U utilisé donc), le ? redonne un comportement greedy à * et +.


---------------
Main/Alt1/Alt2/Alt3
Reply

Marsh Posté le 07-10-2011 à 15:33:53   

Reply

Marsh Posté le 07-10-2011 à 19:24:47    

Ouais je voulais dire ungreedy. Bon à savoir ! :)


---------------
Directeur Technique (CTO)
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed