Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

[HS] Expression reguliere

17 réponses
Avatar
Etienne SOBOLE
salut.

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

10 réponses

1 2
Avatar
Olivier Miakinen
Le 11/07/2008 01:56, Etienne SOBOLE a écrit :

désolé de poser cette question ici, mais je sais pas ou la mettre



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 ?
Avatar
Olivier Miakinen
En attendant une réponse d'Étienne, voici déjà une méthode pour le cas
le plus facile. Comme d'hab je n'ai pas testé, mais ça devrait se lire
assez facilement.

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);
?>
Avatar
Etienne SOBOLE
> 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.



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
Avatar
Olivier Miakinen
Le 12/07/2008 12:55, Etienne SOBOLE a écrit :
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.



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]



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
Avatar
SAM
Olivier Miakinen a écrit :
> Le 12/07/2008 12:55, Etienne SOBOLE a écrit :
>>
>> 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]

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
Avatar
Olivier Miakinen
Le 13/07/2008 09:21, SAM a écrit :

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"



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
Avatar
Etienne SOBOLE
> 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));



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
Avatar
Etienne SOBOLE
> D'accord. Pourquoi ne pas avoir parlé de "null," au lieu de "x2" ?



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
Avatar
Olivier Miakinen
Le 13/07/2008 09:21, SAM a écrit :

Ensuite :
Mais où donc es-tu aller dénicher ce 'preg_replace_callback' ?
(doit quand même falloir fouiller pour trouver cette fonction !)



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.
Avatar
SAM
Résumé depuis f.c.l.php :

========= Etienne SOBOLE a écrit :

je cherche l'expression regulière qui compte un motif précis répété
successivement du genre :
abcx2x2x2x2x2x2pq
je cherche à compter les motif x2

j'aimerai transformer cette chaine en
abc#6pq
indiquant pas là que j'ai 6 fois le motif recherché!

voila.
ca se fait ca avec une expression régulière ???



======== SAM
sans expression régulière :
<http://cjoint.com/?hnbIeQxTmD>

========= Le 12/07/2008 12:55, Etienne SOBOLE a écrit :
>>
>> 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.

====== SAM

Je le fais sans expression régulière :

function compacter(tableau) {
var n = 0;
while(n<tableau.length && tableau[n]==null) n++;
return '@N'+n+'_'+tableau[n];
}
alert(compacter(tData));

======== Etienne SOBOLE a écrit :
>
> Interessant,
> mais j'ai opté pour une méthode plus globale travaillant sur la chaine
> une fois sérialisée, car la structure que je renvoie est trop complexe
> pour que je m'amuse a chercher tous les tableaux.
> Ça 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@
> où x est le nombre de "null," consécutifs trouvés !

========= Olivier Miakinen a écrit :
>
> 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]
> ---------------------------------------------------------------------

========= Olivier Miakinen a écrit :
>
> 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é)

à mon idée ce devrait être plus proche de :

function dorepnull(sujet) {
sujet = sujet.replace(/(?<=[[,])(null,)*null[],]/,
function(match) {
return '#' + match.length/5 + match.substring(match.length-1);
});
return sujet;
}
alert(dorepnull($b));

Bon ... ça marche pô :-(

Erreur : invalid quantifier ?<=[[,])(null,)*null[],]
Code Source :
sujet = sujet.replace(/(?<=[[,])(null,)*null[],]/,

--
sm
1 2