REGEXP et parenthèses

Petit nouveau ! | 8 Messages

23 déc. 2008, 16:28

Bonjour à tous,

j'ai un petit soucis avec l'utilisation d'une expression régulière et n'étant pas un pro dans ce domaine, je préfère m'adresser à vous :-)

En gros ce que j'essaie de faire c'est la chose suivante:
- j'ai dans ma base de données un champs de type texte contenant des user agents
- quand je reçois la visite d'un user agent, je dois comparer celui du visiteur à celui de la base

Le problème c'est que le user agent contient des caractères spéciaux utilisés par les expressions régulières et je n'arrive pas à les échapper.

Voici un exemple:

Dans la base j'ai un champs useragent qui contient:
HTC_P3700 Opera,HTC_P3700 Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11) UP.Link/6.2.3.20.0,Opera/9.5 (Microsoft Windows; PPC; Opera Mobi/1938; U; fr),Opera/9.50 (Windows NT 5.1; U; en),Opera/9.5 (Microsoft Windows; PPC; Opera Mobi/1476; U; en),HTC-P3700-orange/PPC; 480x640; OpVer 30.137.2.732 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11),Opera/9.5 (Microsoft Windows; PPC; Opera Mobi/2392; U; en),Opera/9.5 (Microsoft Windows; PPC; 240x320; HTC_P3650; Opera Mobi/2392; U; fr),Xda_Ignito/480x640 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11),Xda_Ignito/480x640 Opera/9.50 (Windows NT 5.1; U; en),dopod S900_CMCC/5.2.1941/WAP2.0 Profile/MIDP2.0 Configuration/CLDC1.1 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11),HTC_P3490 Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11),Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11) HT02A,HTC_P3700 Opera/9.50 (Windows NT 5.1; U; fr)

et dans ma requête SQL j'effectue:
select * from mabase where useragent regexp 'HTC_P3700 Opera/9.50 (Windows NT 5.1; U; en)'

ça ne marche pas à cause des parenthèses et quand je transforme ma requête pour transformer les parenthèses en [(] et [)], ça ne marche pas non plus, il ne me trouve aucun résultat.

Je ne peux pas supprimer la partie entre les (...) car pour certains user agents, cette zone contient des informations essentielles. Je cherche donc un moyen de reprendre les useragents tels qu'ils rentrent et les comparer avec ceux qui sont dans la base.

Quelqu'un a une idée?

Merci!

Eléphant du PHP | 170 Messages

23 déc. 2008, 20:34

Salut,
ça ne marche pas à cause des parenthèses et quand je transforme ma requête pour transformer les parenthèses en [(] et [)], ça ne marche pas non plus, il ne me trouve aucun résultat.
En faisant précéder les parenthèses d'un triple anti-slash (rien de moins), il semblerait que ça marche.

Sinon pour ton problème, il n'est peut-être pas nécessaire d'utiliser les expressions régulières :
$sql = "SELECT * FROM mabase WHERE LOCATE('HTC_P3700 Opera/9.50 (Windows NT 5.1; U; en)', useragent) <> 0";

Petit nouveau ! | 8 Messages

24 déc. 2008, 14:08

Salut Blof,

J'ai essayé les deux mais malheureusement aucune des solutions ne marche :-(
Aussi bien dans un cas que dans l'autre, ce sont à nouveau ces parenthèses qui semblent poser problème. Si avec le locate, je me content de prendre uniquement le contenu des parenthèses ou seulement ce qu'il y a devant, ça marche mais quand je prend tout, ça ne marche plus. Pareil pour les antislashs.

J'ai une autre contrainte qui es plus liée à la performance et là je ne sais pas si un regexp est meilleur qu'un locate. Je reçois quelques milliers de requêtes par minutes, il faut donc que la base puisse répondre.

Je vais voir si j'ai pas un bouquin sur les expressions régulières sous le sapin :-)

Pas d'autres idées?

Merci
Laurent

[Note : ce message a été posté de manière anonyme avant d'être réattribué à son auteur]

ViPHP
ViPHP | 4039 Messages

24 déc. 2008, 14:37

Juste en passant, mais comparer par expression régulières les users agents a chaque visite, ça risque pas d'être très couteux au niveau des ressources ?

J'utiliserais plutôt une somme de contrôle (crc32) pour générer une suite de chiffres unique, par user-agent, puis trier la dessus. Ce sera plus facile à indexer, et bien plus performant.

il faut juste ajouter un champ dans la db. Mais ça ne vaut que si a chaque fois tu recherche bien l'entièreté du user-agent. Si tu en recherche des parties, ça ne marchera bien sur pas.
Mais qu'importe. (je suis ici - dernier petit projet)
Berze going social.

Petit nouveau ! | 8 Messages

24 déc. 2008, 15:56

Berzemus, c'est une idée, j'avais pensé à quelque chose dans le genre mais je voulais éviter de devoir créer un nouveau champs dans ma base car j'arrive tout doucement à mon quota de place. J'utilise ce champs tel quel pour en afficher son contenu sur le web donc si je passe un coup de crc32 dessus, je ne sais pas revenir en arrière. Je vais essayer de transformer quelques entrées pour voir la place que ça prend et si ça semble tenir la route, je l'appliquerais à toute la base.

Merci pour la suggestion, c'est peut être finalement la chose la plus efficace à faire.

Eléphant du PHP | 170 Messages

24 déc. 2008, 21:16

Je viens de retester le code avec "LOCATE", ça fonctionne parfaitement chez moi.
( Mon champ "useragent" est de type "text" )
Dans la base j'ai un champs useragent qui contient:
HTC_P3700 Opera,HTC_P3700 Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11) UP.Link/6.2.3.20.0,Opera/9.5 (Microsoft Windows; PPC; Opera Mobi/1938; U; fr),Opera/9.50 (Windows NT 5.1; U; en),Opera/9.5 (Microsoft Windows; PPC; Opera Mobi/1476; U; en),HTC-P3700-orange/PPC; 480x640; OpVer 30.137.2.732 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11),Opera/9.5 (Microsoft Windows; PPC; Opera Mobi/2392; U; en),Opera/9.5 (Microsoft Windows; PPC; 240x320; HTC_P3650; Opera Mobi/2392; U; fr),Xda_Ignito/480x640 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11),Xda_Ignito/480x640 Opera/9.50 (Windows NT 5.1; U; en),dopod S900_CMCC/5.2.1941/WAP2.0 Profile/MIDP2.0 Configuration/CLDC1.1 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11),HTC_P3490 Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11),Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11) HT02A,HTC_P3700 Opera/9.50 (Windows NT 5.1; U; fr)

et dans ma requête SQL j'effectue:
select * from mabase where useragent regexp 'HTC_P3700 Opera/9.50 (Windows NT 5.1; U; en)'
- Dans l'exemple que tu donnes, on est d'accord qu'il n'y a pas la chaîne 'HTC_P3700 Opera/9.50 (Windows NT 5.1; U; en)' ?

- Sinon, si tu visualises ton champ via phpMyAdmin, tu ne vois rien qui pourrait expliquer ton pb ? ( présence d'anti-slashs ... )

- Quel est le type de ton champ "useragent" ?