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

Expression régulière...

22 réponses
Avatar
Cenekemoi
Bonjour,

n'étant pas au top sur les expressions régulières, j'en recherche une
qui me permettrait de vider des parties de texte compris entre deux
mot-clés.

Exemple classique avec les mot-clés '<' et '>' afin de retirer les
balises Html : new RegExp("<[^>]*>", "g");

J'aimerais que les deux caractères < et > ci-dessus soient libres, par
exemple: _DEB_ et _FIN_ mais j'ai du mal à ce que tout fonctionne bien.

Mon essai (en m'inspirant de l'exemple ci-dessus):

<script>
var _H1_ = "_DEB_",_H2_ = "_FIN_";

exp = _H1_ +'link rel="stylesheet" href="../styles/drill_print.css"
type="text/css" media="print"'+ _H2_;
exp+= _H1_ +'style'+ _H2_ +'body,td { font-family: Arial; font-size:
9px;}';
exp+= _H1_ +'/style'+ _H2_;
exp+= _H1_ +'/head'+ _H2_;
exp+= _H1_ +'body onload="onLoad();onLoadTest()"'+ _H2_ +'thierry';
exp+= _H1_ +'/body'+ _H2_;

var reg = new RegExp(_H1_ +"[^"+ _H2_ +"]*"+ _H2_, "g");
alert( exp.replace(reg,"") );
</script>

Résultat:
_DEB_link rel="stylesheet" href="../styles/drill_print.css"
type="text/css" media="print"_FIN_body,td { font-family: Arial;
font-size: 9px;}thierry

C'est lié a priori au caractère "_" dans "drill_print", mais ça ne
m'avance guère.

Des idées ?...

Merci d'avance...

--
Cordialement, Thierry ;-)

10 réponses

1 2 3
Avatar
Olivier Miakinen

n'étant pas au top sur les expressions régulières, j'en recherche une
qui me permettrait de vider des parties de texte compris entre deux
mot-clés.

Exemple classique avec les mot-clés '<' et '>' afin de retirer les
balises Html : new RegExp("<[^>]*>", "g");


1) Syntaxe JavaScript
---------------------

Tu peux simplifier l'écriture en écrivant :
/<[^>]*>/g
au lieu de :
new RegExp("<[^>]*>", "g")

Bien entendu ça ne marchera que si l'expression ne contient pas de
« / », mais elle peut à priori contenir des « " ».

2) Expressions régulières PCRE
------------------------------

Tu peux simplifier l'expression en écrivant :
new RegExp("<.*>", "gU")
ou bien sûr :
/<.*>/gU

(U = Ungreedy = non gourmand, ce qui signifie que l'expression prend le
plus petit motif qui marche au lieu d'aller chercher le plus grand).

J'aimerais que les deux caractères < et > ci-dessus soient libres, par
exemple: _DEB_ et _FIN_ mais j'ai du mal à ce que tout fonctionne bien.


Pour des *caractères* différents de < et > cela devrait marcher pareil,
mais pas pour des *chaînes de caractères*.

En effet, avec "_DEB_[^_FIN_]*_FIN_" et la chaîne "_DEB_ MACHIN _FIN_",
le I et le N de MACHIN arrêteront la recherche avant d'aller jusqu'à ton
_FIN_.

En revanche, RegExp("_DEB_.*_FIN", "gU") devrait fonctionner.

[...]

C'est lié a priori au caractère "_" dans "drill_print", mais ça ne
m'avance guère.

Des idées ?...


Tu dois comprendre que [_FIN_] et [^_FIN_] matchent un seul caractère et
pas un mot. D'ailleurs [^_FIN_] est équivalent à [^____FFNI___IN].

Avatar
Olivier Miakinen
Le 19/07/2007 23:26, jé répondais à Cenekemoi :

new RegExp("_DEB_.*_FIN", "gU");


Si le contenu à virer entre _DEB_ et _FIN_ peut s'étendre sur plus d'une
ligne, il faut rajouter l'option s (DOTALL) ou ça ne marchera pas :

new RegExp("_DEB_.*_FIN", "gUs");

Avatar
Olivier Miakinen
Le 19/07/2007 23:31, j'écrivais (à un « _ » près) :

new RegExp("_DEB_.*_FIN_", "gU");


Si le contenu à virer entre _DEB_ et _FIN_ peut s'étendre sur plus d'une
ligne, il faut rajouter l'option s (DOTALL) ou ça ne marchera pas :

new RegExp("_DEB_.*_FIN_", "gUs");


En reprenant ton code, cela donnera donc :

<script>
var _H1_ = "_DEB_",_H2_ = "_FIN_";

exp = [...]

var reg = new RegExp(_H1_ + ".*" + _H2_, "gUs");
alert(exp.replace(reg, ""));
</script>


Avatar
Cenekemoi

n'étant pas au top sur les expressions régulières, j'en recherche une
qui me permettrait de vider des parties de texte compris entre deux
mot-clés.

Exemple classique avec les mot-clés '<' et '>' afin de retirer les
balises Html : new RegExp("<[^>]*>", "g");


1) Syntaxe JavaScript
---------------------

Tu peux simplifier l'écriture en écrivant :
/<[^>]*>/g
au lieu de :
new RegExp("<[^>]*>", "g")


Oui, merci, je le sais ; je le mettais sous cette forme pour être plus
proche du code que je proposais (avec le "<" variable)...


Bien entendu ça ne marchera que si l'expression ne contient pas de
« / », mais elle peut à priori contenir des « " ».

2) Expressions régulières PCRE
------------------------------

Tu peux simplifier l'expression en écrivant :
new RegExp("<.*>", "gU")


Désolé, Olivier, mais je te rappelle que PCRE = Perl Compatible Regular
Expressions.

Si tu utilises le genre d'expression ci-dessus en *javascript*, sous FF
tu obtiens le message :
"invalid regular expression flag U"

...et une erreur de syntaxe sous IE.

Normal, Javascript n'est pas compatible PERL...

--
Cordialement, Thierry ;-)


Avatar
Olivier Miakinen

Tu peux simplifier l'expression en écrivant :
new RegExp("<.*>", "gU")


Désolé, Olivier, mais je te rappelle que PCRE = Perl Compatible Regular
Expressions.

Si tu utilises le genre d'expression ci-dessus en *javascript*, sous FF
tu obtiens le message :
"invalid regular expression flag U"

...et une erreur de syntaxe sous IE.

Normal, Javascript n'est pas compatible PERL...


Ben mince alors ! On m'aurait menti ?

Citation du « Standard ECMA-262, 3rd Edition - December 1999 » intitulé
« ECMAScript Language Specification », chapitre 15.10 :
-----------------------------------------------------------------------
The form and functionality of regular expressions is modelled after the
regular expression facility in the Perl 5 programming language.
-----------------------------------------------------------------------



Note que tout n'est pas perdu. Même si le flag U n'est pas reconnu, la
syntaxe « *? » doit fonctionner pour faire la même chose :

new RegExp("_DEB_.*?_FIN_", "gs");


Avatar
Olivier Miakinen
Le 23/07/2007 11:17, je répondais à Cenekemoi :

Normal, Javascript n'est pas compatible PERL...


Ben mince alors ! On m'aurait menti ?

Citation du « Standard ECMA-262, 3rd Edition - December 1999 » intitulé
« ECMAScript Language Specification », chapitre 15.10 :
-----------------------------------------------------------------------
The form and functionality of regular expressions is modelled after the
regular expression facility in the Perl 5 programming language.
-----------------------------------------------------------------------


Bon, je viens de comprendre en regardant la doc de PCRE. Ce n'est pas
JavaScript qui n'est pas compatible Perl, mais c'est PCRE qui ne l'est
pas complètement, ayant ajouté des options.

<cit. http://www.pcre.org/pcre.txt>
PCRE_UNGREEDY
This option inverts the "greediness" of the quantifiers so that they
are not greedy by default, but become greedy if followed by "?". It is
not compatible with Perl. It can also be set by a (?U) option setting
within the pattern.
</>

PHP est compatible PCRE, mais JavaScript n'est que compatible Perl.

Note que tout n'est pas perdu. Même si le flag U n'est pas reconnu, la
syntaxe « *? » doit fonctionner pour faire la même chose :

new RegExp("_DEB_.*?_FIN_", "gs");


Ça c'est à la fois Perl et PCRE, donc ça doit marcher.


Avatar
Cenekemoi
PHP est compatible PCRE, mais JavaScript n'est que compatible Perl.

Note que tout n'est pas perdu. Même si le flag U n'est pas reconnu,
la syntaxe « *? » doit fonctionner pour faire la même chose :

new RegExp("_DEB_.*?_FIN_", "gs");


Ça c'est à la fois Perl et PCRE, donc ça doit marcher.


Si on enlève le "s", tout baigne ! Merci beaucoup...
Accessoirement, à quoi est sensé servir le "s" ci-dessus en Perl ?

Maintenant, STP, pourrais-tu décrire le rôle dévolu à chacun des trois
caractères ".*?", je te remercie d'avance

J'ai par ailleurs fini par trouver sur le web ta syntaxe mais encadrée
par des parenthèses "(.*?)", quelle différence cela fait-il avec ta
proposition ?

--
Cordialement, Thierry ;-)


Avatar
Olivier Miakinen
PHP est compatible PCRE, mais JavaScript n'est que compatible Perl.

Note que tout n'est pas perdu. Même si le flag U n'est pas reconnu,
la syntaxe « *? » doit fonctionner pour faire la même chose :

new RegExp("_DEB_.*?_FIN_", "gs");


Ça c'est à la fois Perl et PCRE, donc ça doit marcher.


Si on enlève le "s", tout baigne ! Merci beaucoup...


Pourtant, d'après la doc de PCRE c'est bien une option de Perl.

Accessoirement, à quoi est sensé servir le "s" ci-dessus en Perl ?


<cit. http://www.pcre.org/pcre.txt>
PCRE_DOTALL
If this bit is set, a dot metacharater in the pattern matches all char-
acters, including those that indicate newline. Without it, a dot does
not match when the current position is at a newline. This option is
equivalent to Perl's /s option, and it can be changed within a pattern
by a (?s) option setting. A negative class such as [^a] always matches
newline characters, independent of the setting of this option.
</cit.>

Explication en français : par défaut, le métacaractère « point » peut
représenter n'importe quel caractère *sauf* un saut de ligne. Donc la
séquence « .* » ne peut pas aller au delà d'une seule ligne de texte.

Du coup, /_DEB_.*_FIN_/ fonctionnera sur ce premier exemple :

Essai_DEB_sur une seule ligne_FIN_.

... mais pas sur le suivant :

Essai_DEB_sur
plusieurs
lignes_FIN_.

L'option /s (ou PCRE_DOTALL) permet de franchir les sauts de ligne.

Maintenant, STP, pourrais-tu décrire le rôle dévolu à chacun des trois
caractères ".*?", je te remercie d'avance


. = n'importe quel caractère sauf les sauts de ligne (à moins de /s)
* = répéter ce qui précède n'importe quel nombre de fois (y compris
éventuellement 0 fois), et privilégier le résultat le plus long
si plusieurs sont possibles.
*? = idem * mais privilégier le résultat le plus court si plusieurs
sont possibles.

Par exemple, avec la chaîne "_DEB_xx_FIN_ uu _DEB_yy_FIN_" :
/_DEB_.*_FIN_/ --> le « .* » trouvera "xx_FIN_ uu _DEB_yy"
/_DEB_.*?_FIN_/ --> le « .*? » trouvera "xx", puis "yy".

J'ai par ailleurs fini par trouver sur le web ta syntaxe mais encadrée
par des parenthèses "(.*?)", quelle différence cela fait-il avec ta
proposition ?


Aucune, puisque tu ne te sers pas de ces « parenthèses capturantes »
(qui retournent les valeurs trouvées dans 1, 2, 3, etc.). Elles
sont inutiles ici.



Avatar
Cenekemoi
(...)
L'option /s (ou PCRE_DOTALL) permet de franchir les sauts de ligne.


Comme je travaille avec des chaînes sans saut de ligne, je comprend que
cela marche sans le "s"

Maintenant, STP, pourrais-tu décrire le rôle dévolu à chacun des
trois caractères ".*?", je te remercie d'avance


. = n'importe quel caractère sauf les sauts de ligne (à moins de /s)
* = répéter ce qui précède n'importe quel nombre de fois (y compris
éventuellement 0 fois), et privilégier le résultat le plus long
si plusieurs sont possibles.
*? = idem * mais privilégier le résultat le plus court si plusieurs
sont possibles.

Par exemple, avec la chaîne "_DEB_xx_FIN_ uu _DEB_yy_FIN_" :
/_DEB_.*_FIN_/ --> le « .* » trouvera "xx_FIN_ uu _DEB_yy"
/_DEB_.*?_FIN_/ --> le « .*? » trouvera "xx", puis "yy".


Merci beaucoup ! Comme d'habitude avec toi, les explications sont
limpides et argumentées...du coup, je comprend beaucoup mieux certains
rôles particuliers de RegExp que j'ai eu l'occasion de voir

--
Cordialement, Thierry ;-)


Avatar
Cenekemoi
Merci beaucoup ! Comme d'habitude avec toi, les explications sont
limpides et argumentées...du coup, je comprend beaucoup mieux certains
rôles particuliers de RegExp que j'ai eu l'occasion de voir


Olivier,
pendant que j'y suis, l'expression "<[^>]*>" (pour enlever les balises
html) aurait pu être simplifiée en "<.*?>", n'est-il pas ? Ou bien
représente-t-elle autre chose qui m'échappe ?

--
Cordialement, Thierry

PS: les lignes citées ne sont pas de la flagornerie !... ;-)

1 2 3