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

Regex dans une boucle for

8 réponses
Avatar
unbewusst.sein
je ne pige pas un truc concernant les regexps.
si je définis ma regexp en dehors de la boucle for par :

et la boucle :
for(var i=0; i<l; i++){
rgx.exec(os[i].getAttribute('onclick'));
if(parseInt(RegExp.$1,10)==-2){
todel=i;
}
}

la variable todel est settée au coup suivant (aussi) càd qu'elle vaut 1
quand elle devrait valoir 0.

si je définis ma regexp dans la boucle :
for(var i=0; i<l; i++){
var rgx=/load_items\(this, (-?\d{1,3})\);return false/g;
rgx.exec(os[i].getAttribute('onclick'));
if(parseInt(RegExp.$1,10)==-2){
todel=i;
}
}

là, pas de pb ???
j'ai la bonne valeur, pourquoi ?

--
« Les femmes préfèrent les hommes qui les prennent sans les comprendre,
aux hommes qui les comprennent sans les prendre. »
(Marcel Prévost)

8 réponses

Avatar
Bol
je ne pige pas un truc concernant les regexps.
si je définis ma regexp en dehors de la boucle for par :



Avec cette notation je crois qu'il faut recreer la regexp
mais tu reponds toi memeà la question ;-)

for(var i=0; i<l; i++){
rgx.exec(os[i].getAttribute('onclick'));
if(parseInt(RegExp.$1,10)==-2){
todel=i;
}
}



sinon ca ? (copier collé pas testé)

var rgx=/load_items(this, (-?d{1,3}));return false/g;
var r;

for(var i=0; i<l; i++)
if( r = os[i].getAttribute('onclick').match( rgx ) )
if(parseInt(r[1],10)==-2)
todel=i;

A+
Bol
Avatar
unbewusst.sein
Bol wrote:


Avec cette notation je crois qu'il faut recreer la regexp
mais tu reponds toi memeà la question ;-)



ta réponse => +/- que rgx= new ReGexp(...);
je n'aurais pas le même comportement ?

bon je teste vite fait...

pas de pot, avec :
var rgx=new RegExp(/load_items(this, (-?d{1,2}));return false/g);
en dehors de la boucle, j'obtiens :
inputs[0] = 'load_items(this, -1);return false' => '-1'
inputs[1] = 'load_items(this, 4);return false' => '-1'

et dans la boucle :
inputs[0] = 'load_items(this, -1);return false' => '-1'
inputs[1] = 'load_items(this, 4);return false' => '4'

comme j'affiche RegExp.$1, c'est "normal" qu'il faille réinitialiser
RexExp quelque doit la manière de faire :
var rgx=new RegExp(/load_items(this, (-?d{1,2}));return false/g);
ou :
var rgx=/load_items(this, (-?d{1,2}));return false/g;

j'ai essayé ta méthode :
var rgx=/load_items(this, (-?d{1,3}));return false/g;
var r;
for(var i=0; i<l; i++){
if( r = inputs[i].innerHTML.match( rgx ) ){
txt+="inputs["+i+"] = '"+inputs[i].innerHTML+"' => '"+r[1]+"'<br
/>";
}
}

ça donne 'undefined' :
inputs[0] = 'load_items(this, -1);return false' => 'undefined'
inputs[1] = 'load_items(this, 4);return false' => 'undefined'

???

par ailleurs, je ne suis pas paevenu à entrer le motif en string, sans
doute un pb d'escaping :
var rgx=new RegExp("load_items(this, (-?d{1,2}));return false","g");

mon code complet :
------------------------------------------------------------------------
<html><head><title>regex match</title>
<meta http-equiv="Content-Type" content="application/xhtml+xml;
charset=utf-8">
<script>
function match(inp, out){
var rgx=/load_items(this, (-?d{1,2}));return false/g;
rgx.exec(document.getElementById(inp).innerHTML);
document.getElementById(out).innerHTML="With '"+rgx.source+"' gives
:<br />"+RegExp.$1;
}
function doit(){
var log=document.getElementById('log')
var divs=document.getElementsByTagName('div')
var inputs=new Array();
var l=divs.length;
var txt="";
for(var i=0;i<l;i++){
if(divs[i].className=='input'){inputs[inputs.length]=divs[i]}
}
l=inputs.length;
//var rgx=new RegExp("load_items(this, (-?d{1,2}));return
false","g"); // MARCHE PAS, RegExp.$1 RETOURNE ''...
//var rgx=new RegExp(/load_items(this, (-?d{1,2}));return
false/g);
//var rgx=/load_items(this, (-?d{1,2}));return false/g;
for(var i=0;i<l;i++){
var rgx=new RegExp(/load_items(this, (-?d{1,2}));return
false/g);
rgx.exec(inputs[i].innerHTML);
txt+="inputs["+i+"] = '"+inputs[i].innerHTML+"' =>
'"+RegExp.$1+"'<br />";
}
txt+="Seconde méthode :<br />";
var rgx=/load_items(this, (-?d{1,3}));return false/g;
var r;
for(var i=0; i<l; i++){
if( r = inputs[i].innerHTML.match( rgx ) ){
txt+="inputs["+i+"] = '"+inputs[i].innerHTML+"' => '"+r[1]+"'<br
/>";
}
}
log.innerHTML=txt;
}
</script>
</head><body>
<form action="">
<h3>Exemple 1 :</h3>
<div class="input">load_items(this, -1);return false</div><br />
<h3>Exemple 2 :</h3>
<div class="input">load_items(this, 4);return false</div><br />
<input type="button" value="Do it" onClick="doit()">
<h3>Résultats :</h3>
<div id='log'></div>
</form>
</body>
</html>
------------------------------------------------------------------------


--
« Le meilleur de nos convictions ne peut se traduire par des paroles.
Le langage n'est pas apte à tout. »
(Johann Wolfgang von Goethe)
Avatar
Olivier Miakinen
Bonjour,

Le 19/09/2011 19:07, Une Bévue a écrit :

for(var i=0; i<l; i++){
rgx.exec(os[i].getAttribute('onclick'));
if(parseInt(RegExp.$1,10)==-2){
todel=i;
}
}



Je vois potentiellement deux problèmes dans ce code. Enfin... il y en
a un qui est certain, l'autre je n'en suis pas sûr.


Le premier problème, c'est que tu ne testes pas le résultat de exec
pour savoir si RegExp.$1 vient d'être mis à jour ou pas ! À la limite
d'ailleurs tu pourrais lire le résultat du exec (si tant est qu'il ne
soit pas nul) au lieu de lire RegExp.$1.

Enfin, sans changer trop ton code, ça pourrait être :

for (var i=0; i<l; i++){
if (rgx.exec(os[i].getAttribute('onclick'))) {
if (parseInt(RegExp.$1,10) == -2) {
todel=i;
}
}
}


Le second problème, éventuel, serait peut-être d'avoir mis le flag
global (/g) et de ne pas remettre la propriété lastIndex à 0 entre
les deux appels. En fait je n'arrive pas à comprendre pourquoi tu
as mis ce flag global, et si jamais tu ne sais pas pourquoi toi non
plus c'est peut-être qu'il ne le fallait pas.

Donc :

var rgx=/load_items(this, (-?d{1,3}));return false/;


Par ailleurs, bien que ça n'ait aucun rapport avec ton problème, je
voudrais te mettre en garde contre le code trop compact, dans lequel
tu supprimes toutes les espaces qui te semblent inutiles. D'une part
cela le rend plus difficile à lire, et d'autre part tu n'es pas à
l'abri d'une éventuelle évolution du langage. Par exemple, si tu
écris « i==-2 » au lieu de « i == -2 », tu risques d'avoir des
problèmes si un jour existe un opérateur « ==- ». Je sais, ça n'a
que peu de chances d'arriver, mais pourquoi tenter le diable ?


Cordialement,
--
Olivier Miakinen
Avatar
Pierre Goiffon
Le 20/09/2011 22:44, Olivier Miakinen a écrit :
Par ailleurs, bien que ça n'ait aucun rapport avec ton problème, je
voudrais te mettre en garde contre le code trop compact, dans lequel
tu supprimes toutes les espaces qui te semblent inutiles.



Oui tout à fait d'accord ! D'autant que en JavaScript la bonne pratique
est de servir un code minifié, et c'est plutôt un outil (jslint, yui
compressor, ...) qui va le générer, et bien mieux le faire.
Avatar
unbewusst.sein
Olivier Miakinen <om+ wrote:

> je testerai ça dès retour devant mon ordi.

Tu nous tiendras au courant ?



Oui, ça roule !
Ce que je fais maintenant, ça ne change pas grand chose au niveau du
code :
var nb;
//var rgx=new RegExp("load_items(this, (-?d{1,2}));return false");
// ( 1 )
//var rgx=/load_items(this, (-?d{1,2}));return false/; // ( 2 )
var rgx=new RegExp(/load_items(this, (-?d{1,2}));return false/); // (
3 )
for(var i=0;i<l;i++){
var res=rgx.exec(inputs[i].innerHTML);
if(res){
nb=res[1];
}
}
là, ça marche à tous les coups, je veux dire quelque soit la forme de
Regexp : 1 2 ou 3.
en fait res[0] contient toute la sting en entrée (ici
inputs[i].innerHTML).
res[1] ce qui match la première est seule parenthèse ("(-?d{1,2})") =>
c'est ce dont j'ai besoin.
res.index retourne 0 (je suppose que ça signifie que ça match dès le
premier caractère ?

--
« Il vaut mieux taxer les pauvres que les riches car
ils sont beaucoup plus nombreux »
(Margaret Thatcher)
Avatar
Olivier Miakinen
Le 23/09/2011 16:15, Une Bévue a écrit :

[ /load_items(this, (-?d{1,2}));return false/ ]
[...]
for(var i=0;i<l;i++){
var res=rgx.exec(inputs[i].innerHTML);
if(res){
nb=res[1];



Oui, c'est bien ce que j'entendais en disant que tu pouvais utiliser le
résultat du exec() plutôt que RegExp.$1. Je trouve ça plus propre, de la
même façon qu'utiliser un paramètre d'une fonction est en général plus
propre que de passer par une variable globale.

en fait res[0] contient toute la string en entrée (ici
inputs[i].innerHTML).



Si c'est le cas, alors c'est que ta regexp se trouve matcher la totalité
de la chaîne passée en entrée. En fait res[0] est censée contenir le
résultat du match complet ; d'après la doc, c'est res.input qui contient
la chaîne passée en entrée.

Au fait, si res[0] est vraiment égal à inputs[i].innerHTML (et donc à
res.input), ça veut dire que tu n'as pas mis de point-virgule après
« return false ». ;-)

res[1] ce qui match la première et seule parenthèse ("(-?d{1,2})") =>
c'est ce dont j'ai besoin.



Oui. Et res.length doit contenir 2 (nombre d'éléments).

res.index retourne 0 (je suppose que ça signifie que ça match dès le
premier caractère ?



Oui. Et puisque res[0] est égal à res.input, c'est normal que tu aies
res.index = 0.


Prenons un exemple plus simple :
var rgx = /(d{1,2}):(d{1,2})/;
var res = rgx.exec("il est 03:24:57");

Sauf erreur de ma part, tu dois avoir :
res.index = 7
res.input = "il est 03:24:57"
res.length = 3
res[0] = "03:24"
res[1] = "03"
res[2] = "24"

Cordialement,
--
Olivier Miakinen
Avatar
unbewusst.sein
Olivier Miakinen <om+ wrote:

Le 23/09/2011 16:15, Une Bévue a écrit :
>
> [ /load_items(this, (-?d{1,2}));return false/ ]
> [...]
> for(var i=0;i<l;i++){
> var res=rgx.exec(inputs[i].innerHTML);
> if(res){
> nb=res[1];

Oui, c'est bien ce que j'entendais en disant que tu pouvais utiliser le
résultat du exec() plutôt que RegExp.$1. Je trouve ça plus propre, de la
même façon qu'utiliser un paramètre d'une fonction est en général plus
propre que de passer par une variable globale.

> en fait res[0] contient toute la string en entrée (ici
> inputs[i].innerHTML).

Si c'est le cas, alors c'est que ta regexp se trouve matcher la totalité
de la chaîne passée en entrée. En fait res[0] est censée contenir le
résultat du match complet ; d'après la doc, c'est res.input qui contient
la chaîne passée en entrée.

Au fait, si res[0] est vraiment égal à inputs[i].innerHTML (et donc à
res.input), ça veut dire que tu n'as pas mis de point-virgule après
« return false ». ;-)




effectivement, mais dans un onclick, à la fin, est-ce utile ?

> res[1] ce qui match la première et seule parenthèse ("(-?d{1,2})") =>
> c'est ce dont j'ai besoin.

Oui. Et res.length doit contenir 2 (nombre d'éléments).

> res.index retourne 0 (je suppose que ça signifie que ça match dès le
> premier caractère ?

Oui. Et puisque res[0] est égal à res.input, c'est normal que tu aies
res.index = 0.


Prenons un exemple plus simple :
var rgx = /(d{1,2}):(d{1,2})/;
var res = rgx.exec("il est 03:24:57");

Sauf erreur de ma part, tu dois avoir :
res.index = 7
res.input = "il est 03:24:57"
res.length = 3
res[0] = "03:24"
res[1] = "03"
res[2] = "24"




oui, exactement ça, j'ai testé, et si je change rgx to :
var rgx = /(d{1,2}):(d{1,2}):(d{1,2})/;

j'obtiens :
res.index = '7'
res.input = 'il est 03:24:57'
res.length = '4'
res[0] = '03:24:57'
res[1] = '03'
res[2] = '24'
res[3] = '57'

@+
--
« Il vaut mieux taxer les pauvres que les riches car
ils sont beaucoup plus nombreux »
(Margaret Thatcher)
Avatar
Olivier Miakinen
Le 23/09/2011 18:43, Une Bévue a écrit :

Au fait, si res[0] est vraiment égal à inputs[i].innerHTML (et donc à
res.input), ça veut dire que tu n'as pas mis de point-virgule après
« return false ». ;-)



effectivement, mais dans un onclick, à la fin, est-ce utile ?



Non, vraiment pas, c'était juste une remarque en passant (en fait,
initialement j'ai cru qu'il manquait aussi une parenthèses, puis je
me suis aperçu de mon erreur).

Prenons un exemple plus simple :
var rgx = /(d{1,2}):(d{1,2})/;
var res = rgx.exec("il est 03:24:57");

Sauf erreur de ma part, tu dois avoir :
res.index = 7
res.input = "il est 03:24:57"
res.length = 3
res[0] = "03:24"
res[1] = "03"
res[2] = "24"



oui, exactement ça, j'ai testé,



:-D (moi content)

et si je change rgx to :
var rgx = /(d{1,2}):(d{1,2}):(d{1,2})/;

j'obtiens :
res.index = '7'
res.input = 'il est 03:24:57'
res.length = '4'
res[0] = '03:24:57'
res[1] = '03'
res[2] = '24'
res[3] = '57'



Parfait.

Cordialement,
--
Olivier Miakinen