JeuWeb - Crée ton jeu par navigateur
REGEX - mal au crane - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : REGEX - mal au crane (/showthread.php?tid=2687)



REGEX - mal au crane - Ruz - 17-06-2008

Hello!
Bon, je bosse aussi pour optimiser mes transferts de données serveur-client
Donc, ajax me renvoit une chaine que j'ai formatée avec les détails des tuiles...
a savoir:
Citation :[48;32;1;0;;;][47;32;1;0;8;;][46;32;1;0;;;][45;32;1;0;;;][44;32;1;0;10;;]
[43;32;1;0;4;;][42;32;1;0;;;][41;32;1;0;;;][40;32;1;0;8;;][39;32;1;0;1;;]
[38;32;1;0;1;;][37;32;1;0;;;][36;32;1;0;;;][35;32;1;0;;;][34;32;1;0;;;]
[48;33;1;0;;;][47;33;1;0;;;][46;33;1;0;2;;][45;33;1;0;11;;][44;33;1;0;;;]
[43;33;1;0;;;][42;33;1;0;5;;][41;33;1;0;;;][40;33;1;0;10;;][39;33;1;0;;;]
[38;33;1;0;;;][37;33;1;0;3;;][36;33;1;0;;;][35;33;1;0;;;][34;33;1;0;3;;]
[48;34;1;0;;;][47;34;1;0;;;][46;34;1;0;;;][45;34;1;0;10;;][44;34;1;0;;;]
[43;34;1;0;;;][42;34;1;0;;;][41;34;1;0;;;][40;34;1;0;11;;][39;34;1;0;10;;]
[38;34;1;0;;;][37;34;1;0;;;][36;34;1;0;;;][35;34;1;0;;;][34;34;1;0;;;]
[48;35;1;0;;;][47;35;1;0;9;;][46;35;1;0;;;][45;35;1;0;;;][44;35;1;0;4;;]
[43;35;1;0;;;][42;35;1;0;10;;][41;35;1;0;8;;][40;35;1;0;;;][39;35;1;0;;;]
[38;35;1;0;6;;][37;35;1;0;;;][36;35;1;0;;;][35;35;1;0;10;;][34;35;1;0;5;;]
[48;36;1;0;;;][47;36;1;0;10;;][46;36;1;0;;;][45;36;1;0;4;;][44;36;1;0;;;]
[43;36;1;0;10;;][42;36;1;0;5;;][41;36;1;0;;;][40;36;1;0;;;][39;36;1;0;;;]
[38;36;1;0;;;][37;36;1;0;3;;][36;36;1;0;;;][35;36;1;0;;;][34;36;1;0;;;]
[48;37;1;0;3;;][47;37;1;0;4;;][46;37;1;0;;;][45;37;1;0;;;][44;37;1;0;;;]
[43;37;1;0;;;][42;37;1;0;;;][41;37;1;0;;;][40;37;1;0;;;][39;37;1;0;;;]
[38;37;1;0;;;][37;37;1;0;9;;][36;37;1;0;;;][35;37;1;0;;;][34;37;1;0;;;]
[48;38;1;0;;;][47;38;1;0;;;][46;38;1;0;;;][45;38;1;0;11;;][44;38;1;0;3;;]
[43;38;1;0;;;][42;38;1;0;;;][41;38;1;0;;;][40;38;1;0;;;][39;38;1;0;5;;]
[38;38;1;0;;;][37;38;1;0;;;][36;38;1;0;;;][35;38;1;0;;;][34;38;1;0;;;]
[48;39;1;0;;;][47;39;1;0;;;][46;39;1;0;2;;][45;39;1;0;;;][44;39;1;0;;;]

bref: je split sur '][' => j'obtiens un tableau avec mes bouts de tuiles (étape optionnelle intermédiaire destinée à disparaitre)
j'ai donc des trucs comme ceci à décoder:
Citation :[48;39;1;0;;;
48;39;1;0;;;
48;39;1;0;;;]
48;39;1;0;;0M15;
48;39;1;0;;18;
48;39;1;0;14;1H54122;8

mes règles
case = [X;Y;Z;Sol;Decor(optionnel);Etre (optionnel);Objet(optionnel)]

les 4 premiers chiffres existent toujours
Decor: un ID ou rien
Etre: (rien si rien sur la case)
(0 ou 1) (être libre ou pas (combat))
M ou P ou H= Monstre / Perso du joueur / Humainoïde d'un autre joueur
ID du truc vivant

Objet
Liste des ID des objets sur la case, séparés par des virgules (rien, si y en a pas)



et je tente ma regex:
Citation :var reg=new RegExp("[\[]{0,1}([0-9])+[;]+([0-9])+[;]+([0-9])+[;]+([0-9]){0,1}[;]+([0-9]){0,1}[;]+([0-9]{1}[MPH]{1}[0-9]{1,}){0,}[;]+([0-9,]{0,})+[\]]{0,1}", "g");
var d = reg.exec(tab);
mais évidemment, ca foire...
et j'ai du mal à trouver la cause (faut dire, j'en fais pas souvent, des regex ^^)

Y a une bonne ame pour me guider sur les erreurs?


RE: REGEX - mal au crane - Ruz - 17-06-2008

...
C'est tellement con que j'y ai meme pas pensé ^^
merci

et de fait, ca devrait accélérer le schmilibilik ^^
mais bon, pour le fun: où que ca coince, selon vous?


RE: REGEX - mal au crane - z3d - 17-06-2008

Je pense que tu devrais revoir l'approche de ton système je pense qu'il serait plus judicieux d'utiliser JSON, au moins tes informations seront structurer des la réception, ce qui te lévera une belle épine du pied.

En PHP, il existe des fonctions tel que json_encode et json_decode.
Code PHP :
<?php 
mixed json_decode
( string $json [, bool $assoc ] )
string json_encode ( mixed $value )

Sinon pour le fun j'aurai plutôt vu l'expression suivante :
Code PHP :
<?php 
[{1,1} // Le premier crochet
([0-9]+;){3,3} // X; Y; Z; SOL
([0-9]+)?; // Décor
([0-9]+[MPH][0-9]+)?; // Etre
([0-9,]){0,} // Objet
]{1,1} // Dernier crochet



RE: REGEX - mal au crane - Psykose - 17-06-2008

Tu peux envoyer les donnees comme ceci :
Code :
nb; nb; nb; nb; nb;[Case]

après tu traites la chaine comme ceci :
Code PHP :
<?php
$Exploo
= explode("[Case] ", $_POST['donnees_ajax']);
$LongueurExploo = count($Exploo);

for(
i = 0; i != $LongueurExploo; i++){
$SubExplode = explode("; ",$Exploo[i]);
$PosX = $SubExplode[0];
$PosY = $SubExplode[1];
$PosZ = $SubExplode[2];

$Sol = $SubExplode[3];
$Decor = $SubExplode[4];
$Etre = $SubExplode[5];
}
?>

EDIT : Oups pas vu les autres réponses, désolé ...


RE: REGEX - mal au crane - Ziliev - 21-06-2008

En grand amoureux des regex que je suis, je tente ma chance ... Désolé pour al couleur mais j'ai pas trouvé de meilleur moyen de rendre le tout lisible, en faisant bien al distinction entre texte et regex (la balise php est bien mais elle bouffe mes échappements ...).

Citation :[\[]{0,1}([0-9])+[;]+([0-9])+[;]+([0-9])+[;]+([0-9]){0,1}[;]+([0-9]){0,1}[;]+([0-9]{1}[MPH]{1}[0-9]{1,}){0,}[;]+([0-9,]{0,})+[\]]{0,1}

Beaucoup de problèmes pour moi (ca veut pas forcément dire que c'est faux, simplement que c'est pas la facon dont moi je les écris, mais je suis incapable de faire la distinction avec certitude):

- Déja tu mets des crochets qui servent à rien. "[;]+" tu peux l'écrire ";" ca marche tout aussi bien (dans notre cas), c'est même plus juste en fait parce que le "+" impliquerait que tu peux avoir plusieurs point virgule de suite alors que dans ce que tu écris c'est pas souhaitable.

- Idem pour le crochet de départ ou pour les "{1}", quand tu veux qu'un signe ne soit pris qu'une seule fois ne met tout simplement pas de caractère de comptage (+ * ? {} ...), ca allège ta regex et rend les erreurs mieux visibles.

- Il y a des raccourcis aussi, comme "+" qui vaut "{1,}", ou "*" qui vaut "{0,}" ou encore "?" qui vaut "{0,1}".

- Donc:

[\[]{0,1}([0-9])+[;]+([0-9])+[;]+([0-9])+[;]+([0-9]){0,1}[;]+([0-9]){0,1}[;]+([0-9]{1}[MPH]{1}[0-9]{1,}){0,}[;]+([0-9,]{0,})+[\]]{0,1}
devient
\[?([0-9])+;([0-9])+;([0-9])+;([0-9])?;([0-9])?;([0-9][MPH][0-9]+)*;([0-9,]*)+\]?

- Ensuite tes parenthèses. Si tu les veux capturantes elles sont mal placées, il faut englober le + après le [0-9] si tu veux capturer tout le nombre. Si tu veux aps capturer elles ne servent à rien, [0-9]+ marche tout aussi bien que ([0-9])+. Corrigeons en gardant l'hypothèse de capture:
\[?([0-9]+);([0-9]+);([0-9]+);([0-9]?);([0-9]?);([0-9][MPH][0-9]+)*;([0-9,]*)+\]?

- On commence à y voir plus clair: "([0-9][MPH][0-9]+)*" est juste mais pas tout à fait exact, c'est plus un "?" qu'un "*" qu'il te faut, ta question ici c'est soit il y a tout ca soit il n'y a rien.
\[?([0-9]+);([0-9]+);([0-9]+);([0-9]?);([0-9]?);([0-9][MPH][0-9]+)?;([0-9,]*)+\]?

- Le dernier tronçon est mal défini, j'imagine qu'il n'existe pas que 10 objets numérotés de 0 à 9 mais que certains objets ont des identifiants à deux chiffres, et ton tronçon ne tiens pas compte de l'ordre des caractères puisque c'est un choix parmi des crochets. Pour être plus précis il faudrait:
((?:[0-9]+,)*) si tu choisis de mettre toujours une virgule à la fin, même quand il n'y a pas d'objet après (un nombre suivi d'une virgule répété X fois, X=0 possible. Le "?:" indique une parenthèse non capturante, si tu veux en plus capturer chaque objet séparement c'est plus compliqué encore, là tu capturera la liste).
((?:[0-9]+,)*[0-9]*) si tu choisis d'utiliser des virgules seulement entre les identifiants. Plus propre mais plus lourd.

- Attardons nous sur les 4 premières coordonnées. TU dis qu'elles sont pareilles, pourtant tu nous écris ca:
([0-9]+);([0-9]+);([0-9]+);([0-9]?);
Moi ce que je vois c'est que les 3 premières sont pareilles, mais que la quatrième c'est un chiffre qui peut exister ou non. On peut simplifier tout ca en:
(?:([0-9]+);){4}
4 fois un nombre suivi d'un point virgule à capturer, le "?:" indique une parenthèse non capturante qui sert simplement à définir ce qui doit apparaitre 4 fois.

\[?([0-9]+);([0-9]+);([0-9]+);([0-9]?);([0-9]?);([0-9][MPH][0-9]+)?;((?:[0-9]+,)*[0-9]*)\]?
devient
\[?(?:([0-9]+);){4}([0-9]?);([0-9][MPH][0-9]+)?;((?:[0-9]+,)*[0-9]*)\]?
("?:" pour ne pas capturer toujours)

- Ton 5eme morceau est sensé être un ID ou rien, là ce que je vois c'est "un chiffre ou rien" puisqu'on a un "?". Un "*" serait plus adapté, il permettrait qu'il y ait plusieurs chiffres ou rien. Donc:
\[?(?:([0-9]+);){4}([0-9]*);([0-9][MPH][0-9]+)?;((?:[0-9]+,)*[0-9]*)\]?

- Encore un petit détail, il ne faut pas oublier le "^" en dévut de regex et le "$" en fin, sinon il cherchera cette regex dans ta chaine, mais rien ne te garantira que ce ne soit pas qu'une sous-chaine qu'il trouvera. "^" indique que le premier caractère de la regex doit correspondre au premier caractère de la chaine, et "$" que le dernier de la regex correspond au dernier de la chaine.

- Autre détail qui tue qui vient de me sauter à la figure en testant mon résultat: gare aux échappements de crochets ! Généralement il faut double échapper pour que ca fonctionne (en tout cas dans l'exemple qui av suivre).

Donc au final:
^\\[?(?:([0-9]+);){4}([0-9]*);([0-9][MPH][0-9]+)?;((?:[0-9]+,)*[0-9]*)\\]?$

Une chaine plus courte et plus précise.


Maintenant qu'on y est, l'instant de vérité: est ce que ca marche (quand t'as passé une demi heure à la construire ta regex c'est le moment ou tu te met à trembler :p). Un petit script facile pour vérifier tout ca:


Code PHP :
<?php 
<html>
<
head>
<
script>
function
pwet()
{
var
regex = new RegExp("^\\[?(?:([0-9]+);){4}([0-9]*);([0-9][MPH][0-9]+)?;((?:[0-9]+,)*[0-9]*)\\]?$", "g");
var
Chaine1 = "[48;39;1;0;;;";
var
Chaine2 = "48;39;1;0;;;";
var
Chaine3 = "48;39;1;0;;;]";
var
Chaine4 = "48;39;1;0;;0M15;";
var
Chaine5 = "48;39;1;0;;18;";
var
Chaine6 = "48;39;1;0;14;1H54122;8"

if (Chaine1.match(regex)) { document.writeln("TRUE<br>"); } else { document.writeln("FALSE<br>"); }
if (
Chaine2.match(regex)) { document.writeln("TRUE<br>"); } else { document.writeln("FALSE<br>"); }
if (
Chaine3.match(regex)) { document.writeln("TRUE<br>"); } else { document.writeln("FALSE<br>"); }
if (
Chaine4.match(regex)) { document.writeln("TRUE<br>"); } else { document.writeln("FALSE<br>"); }
if (
Chaine5.match(regex)) { document.writeln("TRUE<br>"); } else { document.writeln("FALSE<br>"); }
if (
Chaine6.match(regex)) { document.writeln("TRUE<br>"); } else { document.writeln("FALSE<br>"); }
}
</
script>
</
head>
<
body onload="pwet()">
</
body>
</
html>

Verdict:

Citation :TRUE
TRUE
TRUE
TRUE
FALSE
TRUE

Horreur, une erreur. Le soucis c'est que l'erreur ne vient pas de ma regex adorée mais de ton énoncé: qu'est ce que c'est que ce "18" en avant dernier tronçon de la chaine 5 ?! Ca ne correspond pas à ce que tu nous a décrit ...


RE: REGEX - mal au crane - Ruz - 22-06-2008

exact ^^
erreur de frappe... le 18 serait en dernier...
Sinon, on peut oublier les crochets d'entrée/sortie... je les vire en splittant entre les cases, et je supprime le rpemier et dernier caractère avant de splitter... donc, deja ca en moins a gérer ^^

Sinon, cool le message... j'apprends des trucs (enfin, ca les remet en tete... y a juste l'* que je connaissais pas, je pense)