désolé de poser cette question ici, mais je sais pas ou la mettre
je cherche l'expression regulière qui compte un motif précis répété
succéssivement
genre j'ai la chaine
abcx2x2x2x2x2x2pq
je cherche a compte les motif x2
j'aimerai transformer cette chaine en
abc#6pq
indiquant pas la que j'ai 6 fois le motif recherché!
voila.
ca se fait ca avec une expression régulière ???
merci
Etienne
En l'absence d'un groupe consacré aux expressions régulières, ces
questions ont traditionnellement été acceptées dans ce groupe pourvu
qu'il s'agisse quand même de leur usage à travers PHP.
> je cherche l'expression regulière qui compte un motif précis répété
> succéssivement
>
> genre j'ai la chaine
> abcx2x2x2x2x2x2pq
> je cherche a compte les motif x2
>
> j'aimerai transformer cette chaine en
> abc#6pq
>
> indiquant pas la que j'ai 6 fois le motif recherché!
>
> voila.
> ca se fait ca avec une expression régulière ???
Il y a plusieurs méthodes possibles, utilisant selon le cas preg_match
ou preg_match_all + preg_replace, ou preg_replace seul, ou peut-être
preg_replace_callback.
Pour te répondre, je voudrais savoir d'abord :
1) Est-ce que le x2 peut se trouver à plusieurs endroits dans la chaîne,
et doit-il être traité à chaque fois ? Par exemple :
abcx2x2x2defx2x2pq -> abc#3defx2x2pq ou abc#3def#2pq ?
2) Dans le cas ci-dessus, est-il gênant de regrouper les comptes ?
abcx2x2x2defx2x2pq -> abc#5defpq
3) Y a-t-il des caractères ou des séquences de caractères que tu es sûr
de ne jamais rencontrer, et qui peuvent servir temporairement (y compris
par exemple le caractère #) ?
4) Est-ce que tu peux connaître une limite au nombre de x2 ?
Le 11/07/2008 02:32, Olivier Miakinen je répondais à Étienne Sobole :
>>
>> genre j'ai la chaine
>> abcx2x2x2x2x2x2pq
>> je cherche a compte les motif x2
>>
>> j'aimerai transformer cette chaine en
>> abc#6pq
>
> 4) Est-ce que tu peux connaître une limite au nombre de x2 ?
Mettons que cette limite soit un entier représenté par la constante
MAXREPLACE.
<?php
$array_pattern = new array();
$array_replace = new array();
$pattern = "";
for ($i = 1; $i <= MAXREPLACE; $i++) {
$pattern .= 'x2';
array_unshift($array_pattern, "/$pattern/");
array_unshift($array_replace, "#$i");
}
$result = preg_replace($array_pattern, $array_replace, $subject);
?>
ben c'est qu'a moitie lié au php.
En fait j'utilise json coté javascript et json_decode cote php.
le problème est que si en javascript j'ai un truc genre
var tData = [];
tData[5] = 10;
la serialisation json va me donner un truc genre
[null,null,null,null,null,10]
ce que je souhaite faire c'est remplacer ca par
[@N5_10]
afin de réduire le flot de données a envoyer.
Peut etre effectivement que dans le newsgroup javascript, ca aurai plus sa
place.
désolé.
> 1) Est-ce que le x2 peut se trouver à plusieurs endroits dans la chaîne,
> et doit-il être traité à chaque fois ? Par exemple :
> abcx2x2x2defx2x2pq -> abc#3defx2x2pq ou abc#3def#2pq ?
oui ca peut
> 2) Dans le cas ci-dessus, est-il gênant de regrouper les comptes ?
> abcx2x2x2defx2x2pq -> abc#5defpq
oui c'est génant ;)
> 3) Y a-t-il des caractères ou des séquences de caractères que tu es sûr
> de ne jamais rencontrer, et qui peuvent servir temporairement (y compris
> par exemple le caractère #) ?
oui #, @ et _
> 4) Est-ce que tu peux connaître une limite au nombre de x2 ?
non pas vraiement.
Etienne
D'accord. Pourquoi ne pas avoir parlé de "null," au lieu de "x2" ?
> ce que je souhaite faire c'est remplacer ca par
> [@N5_10]
> afin de réduire le flot de données a envoyer.
C'était #5 au début et non @N5_ ! Bon, voici une proposition en PHP,
tu peux l'adapter pour y mettre les caractères que tu veux à la place
de '#'.
---------------------------------------------------------------------
<?php
header("Content-Type: text/plain");
function repnull($matches)
{
$count = strlen($matches[0]) / 5;
return '#' . $count . substr($matches[0], -1);
}
function dorepnull($subject)
{
return preg_replace_callback('/(?<=[[,])(null,)*null[],]/',
'repnull', $subject);
}
$a = '[null,null,null,null,null]';
$b = '[a,null,b,null,null,c,null,d]';
$c = '[nullard,annulle,null,tronull,"null",null,nul]';
echo $a . "\n-> " . dorepnull($a) . "\n";
echo $b . "\n-> " . dorepnull($b) . "\n";
echo $c . "\n-> " . dorepnull($c) . "\n";
?>
---------------------------------------------------------------------
Le résultat de l'exécution est :
---------------------------------------------------------------------
[null,null,null,null,null]
-> [#5]
[a,null,b,null,null,c,null,d]
-> [a,#1,b,#2,c,#1,d]
[nullard,annulle,null,tronull,"null",null,nul]
-> [nullard,annulle,#1,tronull,"null",#1,nul]
---------------------------------------------------------------------
S'il y en a que ça intéresse (toi ou quelqu'un d'autre) je peux
expliquer pourquoi ça marche.
Cordialement,
--
Olivier Miakinen
Alors en JS :
function compacter(tableau) {
var n = 0;
while(n<tableau.length && tableau[n]==null) n++;
return '@N'+n+'_'+tableau[n];
}
alert(compacter(tData));
Bon ... ça ne résoudra pas :
tData[5] = 'ab';
tData[15] = 'zx';
ni :
tData.length = 20;
tData[6] = 'fg';
> S'il y en a que ça intéresse (toi ou quelqu'un d'autre) je peux
> expliquer pourquoi ça marche.
Ben moi, par exemple.
Et non seulement "pourquoi" mais "comment"
J'arrive bien à bidouiller un truc laborieux en JS(*) sans reg
expression, mais ... en PHP avec reg expression ... je nage.
d'abord :
que devient le $matches de repnull($matches)
dans dorepnull($subject) ?
Ensuite :
Mais où donc es-tu aller dénicher ce 'preg_replace_callback' ?
(doit quand même falloir fouiller pour trouver cette fonction !)
Je ne vois même pas la différence entre : 'preg_split' et 'explode' :-(
> $a = '[null,null,null,null,null]';
> $b = '[a,null,b,null,null,c,null,d]';
> $c = '[nullard,annulle,null,tronull,"null",null,nul]';
Et si tu as un bon moment tu pourras expliquer :
/(?<=[[,])(null,)*null[],]/
en particulier : [] (pourquoi ce n'est pas \[\] ?)
dans : *null[],]/ (comment l'expression repère les bons crochets ?)
mais aussi : (?<=[[,])
(*) à voir ici si on veut :
<http://cjoint.com/?hnbIeQxTmD>
J'étions parti du truc du genre :
abcx2x2x2x2x2x2pqx3x2zzbcx2x2x2x2xyz
et non pas d'un array
--
sm
Allons-y, et je vais commencer par l'expression régulière :
/(?<=[[,])(null,)*null[],]/
Tout d'abord, je suppose que tout le monde connaît les classes de
caractères, qui représentent toujours *un* caractère choisi parmi
plusieurs. Par exemple [0123456789] représente un chiffre de 0 à 9,
mais [0-9] représente la même chose. On voit que le caractère '-'
est spécial dans une classe de caractères, et si on veut l'inclure
il faut le mettre au début [-0-9] ou à la fin [0-9-]. Mais le
caractère ']' est spécial lui aussi ! Si on veut l'inclure, on ne
peut le mettre qu'au début : []0-9].
Ainsi, « [],] » est la classe de caractères qui représente soit un
crochet ']' soit une virgule ','. Quant à « [[,] », il représente
soit un crochet '[' soit une virgule ','.
Je ne ferai pas l'affront d'expliquer '*', et il peut rester un seul
truc un peu mystérieux : « (?<= <quelque chose> ) ». Il s'agit d'une
assertion positive arrière (positive lookbehind assertion) qui vérifie
que la chaîne en question se trouve bien avant celle que l'on veut
récupérer, mais sans la récupérer. Ainsi, (?<=,)null, trouvera bien
« null, » dans « ,null, » mais pas dans « ,tronull, ».
Au final, /(?<=[[,])(null,)*null[],]/ trouvera :
null,
null]
null,null,
null,null]
null,null,null,
null,null,null]
null,null,null,null,
null,null,null,null]
et ainsi de suite, mais *seulement* après une virgule ou un crochet ouvrant.
Vu que j'utilise preg_replace_callback, le résultat du match sera envoyé
à la fonction repnull, qui trouve le match complet dans $matches[0] et
le contenu d'éventuelles parenthèses captruantes dans $matches[1], etc.
(mais je ne m'en sers pas). Mettons qu'elle reçoive par exemple la
chaîne "null,null]", de longueur 10. Le nombre de null est 10/5 = 2,
calculé par :
$count = strlen($matches[0]) / 5;
Je rajoute '#' devant, et derrière je veux rajouter ',' ou ']' selon ce
qu'il y avait au départ, ce qui se fait par substr($matches[0], -1).
Dans ce cas précis :
'#' . $count . substr($matches[0], -1)
vaut :
'#' . 2 . ']'
Et voilà !
> d'abord :
> que devient le $matches de repnull($matches)
> dans dorepnull($subject) ?
Il est remplacé par la chaîne envoyée en retour de repnull(). Ainsi,
"null,null]" est remplacé par "#2]".
> Ensuite :
> Mais où donc es-tu aller dénicher ce 'preg_replace_callback' ?
> (doit quand même falloir fouiller pour trouver cette fonction !)
La fouille n'est pas bien longue, car la doc est bien faite de ce point
de vue-là. Par exemple, sur la page <http://fr.php.net/preg_replace> tu
vois dans la colonne de gauche toutes les fonctions apparentées :
# preg_grep
# preg_last_error
# preg_match_all
# preg_match
# preg_quote
# preg_replace_callback
# preg_replace
# preg_split
Il suffit d'un clic pour visiter la doc de chacune.
> Je ne vois même pas la différence entre : 'preg_split' et 'explode' :-(
'explode' ne traite que des chaînes statiques, 'preg_split' des
expressions régulières. Je crois que JavaScript a une seule fonction
pour cela, mais c'est grace au fait qu'il existe un type RegExp, non ?
> Et si tu as un bon moment tu pourras expliquer :
> /(?<=[[,])(null,)*null[],]/
> en particulier : [] (pourquoi ce n'est pas \[\] ?)
Parce que je ne cherche pas une séquence de *quatre* caractères "[],]"
mais *un* seul caractère qui est soit "]" soit ",".
> dans : *null[],]/ (comment l'expression repère les bons crochets ?)
> mais aussi : (?<=[[,])
Cf. les explications ci-dessus à propos des classes de caractères.
Cordialement,
--
Olivier Miakinen
Interessant,
mais j'ai opté pour une méthode plus global travaillant sur la chaine une
fois sérialisée, car la structure que je renvoi est trop complexe pour que
je m'amuse a chercher tous les tableaux ca donne.
var expr = /(null,)+/
var tRes = expr.exec(sDossier);
while (tRes)
{
var sDossier = sDossier.replace(expr, "@N" + (tRes[0].length /
tRes[1].length) + "@");
var tRes = expr.exec(sDossier);
}
et ca remplace une liste de null, par @Nx@
ou x ext les nombre de null, consecutif trouvé !
voila
A+
Etienne
parce que il n'y a pas que les null, à remplacer...
j'ai pas voulu entrer dans un cas particulier.
> C'était #5 au début et non @N5_ ! Bon, voici une proposition en PHP,
Idem. c'etait pas encore vraiment défini ce que je voulais utiliser au
final.
> S'il y en a que ça intéresse (toi ou quelqu'un d'autre) je peux
> expliquer pourquoi ça marche.
J'ai bien compris ton code.
Merci, c'est cool.
Mais pour être honete ma question originale portait sur les expressions
régulières.
Je voulais savoir si une expression pouvait faire le travail toute seule
sans l'aide d'un script.
D'un autre coté, la solution que tu donnes est tres bien.
je vais pas passer 15 jours a chercher :) sinon je suis pas l'à d'avoir fini
Merci
A bientot
Etienne
Tiens, il semblerait que ce soit possible en JavaScript aussi depuis la
version 1.3 :
http://developer.mozilla.org/fr/docs/R%C3%A9f%C3%A9rence_de_JavaScript_1.5_Core:Objets_globaux:String:replace#Exemple_:_utilisation_d.27une_fonction_inline_modifiant_les_caract.C3.A8res_trouv.C3.A9s
Donc :
sujet.replace('/(?<=[[,])(null,)*null[],]/',
function(match) {
count = strlen(match)/5;
last = match.substring(strlen(match)-1);
return '#' + count + last;
});
(non testé)
Je n'ai pas le temps de rappeler le contexte pour faire suivre dans
fr.comp.lang.javascript, mais ne pas hésiter à le faire s'il y a besoin
de poursuivre les recherches dans ce langage.
Comme ça ne fonctionne pas et en particulier la RegExp, je tente la
chose ...
(en essayant au mieux de mes possibilités bien réduites).
<487a23f8$0$915$ba4a...@news.orange.fr>
--
sm