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

a propos des regexpr

8 réponses
Avatar
kurtz le pirate
bonsoir,

est-il possible dans une regexpr d'utiliser les $1,$2,... de la regexpr
elle-même du genre /(motif1).*($1)/ le $1 representant ce qui
correspond à motif1 ?


merci

--
klp

8 réponses

Avatar
VN
kurtz le pirate wrote:
bonsoir,

est-il possible dans une regexpr d'utiliser les $1,$2,... de la regexpr
elle-même du genre /(motif1).*($1)/ le $1 representant ce qui
correspond à motif1 ?


merci



Juste testé:

#!/usr/bin/perl

$str = "motif1 motif1 motif1";
print "okn" if $str =~ m@(motif1).*$1s$1@;

:-)

Avatar
Stephane Chazelas
2007-07-06, 16:15(+02), VN:
kurtz le pirate wrote:
bonsoir,

est-il possible dans une regexpr d'utiliser les $1,$2,... de la regexpr
elle-même du genre /(motif1).*($1)/ le $1 representant ce qui
correspond à motif1 ?


merci



Juste testé:

#!/usr/bin/perl

$str = "motif1 motif1 motif1";
print "okn" if $str =~ m@(motif1).*$1s$1@;
[...]


Oui, mais ca ne renvoie OK que parce que "motif1 motif1 motif1"
matche "(motif1).*s" car "$1" est "".

La syntaxe est m@(motif1).*1s1@

~$ echo aa | perl -ne 'print if /(a)$1/'
aa
~$ echo ab | perl -ne 'print if /(a)$1/'
ab
~$ echo ab | perl -ne 'print if /(a)1/'
~$ echo aa | perl -ne 'print if /(a)1/'
aa

--
Stéphane


Avatar
Klaus
On Jul 5, 7:45 pm, kurtz le pirate wrote:
est-il possible dans une regexpr d'utiliser les $1,$2,... de la regexpr
elle-même du genre /(motif1).*($1)/ le $1 representant ce qui
correspond à motif1 ?


http://perl.enstimac.fr/DocFr/perlretut.html#extraire%20ce%20qui%20est%20re connu

======================== ====================
Associées avec les variables $1, $2, ..., on trouve les
références arrières : 1, 2, ... Les références arrières so nt
simplement des variables de reconnaissance qui peuvent
être utilisées à l'intérieur de l'expression rationnelle. C'est
une fonctionnalité vraiment sympathique - ce qui est reconnu
plus tard dans une expression rationnelle peut dépendre de ce
qui a été reconnu plus tôt dans l'expression rationnelle.
Supposons que nous voulons chercher les mots doublés dans
un texte comme 'the the'. L'expression rationnelle suivante trouve
tous les mots de trois lettres doublés avec un espace entre les
deux :

/(www)s1/;

Le regroupement affecte une valeur à 1 et donc la même
séquence de 3 lettres est utilisée pour les deux parties.
======================== ====================



--
Klaus


Avatar
kurtz le pirate
In article ,
Klaus wrote:

http://perl.enstimac.fr/DocFr/perlretut.html#extraire%20ce%20qui%20est%20recon
nu




... enstimac est dans les choux ce matin mais en relisant pour la x ième
fois le camelbook, j'ai aussi trouvé les 1,2... que j'ai tout de suite
appliqué à mes besoins :

while (<INFILE>) {
chomp;
/<(.*)>(.*)</1>/;
if ($1) {
if ($1 eq "AppName") {
$options=$2;
}
else {
($datas{$options}{$1})?($datas{$options}{$1}.=",$2"):($datas{$options}{$1
}=$2);
}
}
}


...et ça marche super bien :)



--
klp

Avatar
Klaus
On Jul 7, 8:10 am, kurtz le pirate wrote:
/<(.*)>(.*)</1>/;
if ($1) {
if ($1 eq "AppName") {


Tester "if ($1)" est dangereux et potentiellement faux.

Pour être correct il faut écrire:

if (/<(.*)>(.*)</1>/) {
if ($1 eq "AppName") {


Mais plus important:
il me semble que le but du programme et repérer des éléments appari és,

voir Perlfaq4: "Comment repérer des éléments appariés ou imbriqué s ?"

++ Ceci ne peut être réalisé en une seule expression régulière,
++ même très compliquée. Pour trouver quelque chose se
++ situant entre deux caractères simples, un motif comme
++ /x([^x]*)x/ mettra les morceaux de l'intervalle dans $1.
++ Lorsque le séparateur est de plusieurs caractères, il
++ faudrait en utiliser un ressemblant plus à /alpha(.*?)omega/.
++ Mais aucun de des deux ne gère les motifs imbriqués.
++ Pour les expressions imbriquées utilisant (, {, C([} ou <
++ comme délimiteurs, utilisez le module CPAN
++ Regexp::Common ou voyez (??{ code }) dans la page de
++ manuel perlre. Pour les autres cas, il vous faudra écrire un
++ analyseur.

--
Klaus

Avatar
Paul Gaborit
À (at) Sat, 07 Jul 2007 08:10:01 +0200,
kurtz le pirate écrivait (wrote):
In article ,
Klaus wrote:

http://perl.enstimac.fr/DocFr/perlretut.html#extraire%20ce%20qui%20est%20recon
nu




... enstimac est dans les choux ce matin[...]


Oui. Il y avait une maintenance électrique générale planifiée samedi
matin et lors de la remise en route, la climatisation de la salle des
serveurs n'est pas repartie... et la petite climatisation de secours
n'aurait pas tenu un week-end entier avec des pointes à plus de 35
degrés ! Les serveurs non prioritaires (entre autres, le miroir CPAN
et la documentation Perl en français) ont donc été arrêtés jusqu'à ce
matin.

Désolé pour cette coupure...

--
Paul Gaborit - <http://perso.enstimac.fr/~gaborit/>
Perl en français - <http://perl.enstimac.fr/>


Avatar
kurtz le pirate
In article ,
Klaus wrote:

Tester "if ($1)" est dangereux et potentiellement faux.

Pour être correct il faut écrire:

if (/<(.*)>(.*)</1>/) {
if ($1 eq "AppName") {



d'ailleurs en y réfléchissant un peux mieux, c'est plutôt $2 qu'il faut
tester.

ce que je ne comprends pas c'est que mon script me donne bien le
résultat attendu :((

je vais relire le perlfaq4 comme tu le suggère.


--
klp

Avatar
Klaus
On Jul 9, 7:07 pm, kurtz le pirate wrote:
In article ,

Klaus wrote:
Tester "if ($1)" est dangereux et potentiellement faux.

Pour être correct il faut écrire:

if (/<(.*)>(.*)</1>/) {
if ($1 eq "AppName") {



[ snip ]

ce que je ne comprends pas c'est que mon script me donne bien le
résultat attendu :((


Un test qui donne toujours le bon résultat est un signal pour tester
encore mieux :))

Par exemple, quand je veux tester la regexp /<(.*)>(.*)</1>/ avec un
"if ($1) {..." derrière
(je sais, la partie "if ($1) {...." n'est pas propre , mais je veux la
tester)

...je peux, par exemple, écrire un programme ("test.pl") :

========================= ===
use strict;
use warnings;

while (<DATA>) { chomp;
print "'$_' =~ /<(.*)>(.*)</1>/ ";
/<(.*)>(.*)</1>/;
if ($1) {
print "trouve $1 = '$1'n";
}
else {
print "non trouven";
}
}
__DATA__
<a>1</z>
<b>2</b>
<c>3</c>
========================= ===

Le résultat du programme "test.pl" est bon:
========================= ===
'<a>1</z>' =~ /<(.*)>(.*)</1>/ non trouve
'<b>2</b>' =~ /<(.*)>(.*)</1>/ trouve $1 = 'b'
'<c>3</c>' =~ /<(.*)>(.*)</1>/ trouve $1 = 'c'
========================= ===

On pourrait croire que le test est bon, mais si je renverse les lignes
<DATA>...

========================= ===
__DATA__
<c>3</c>
<b>2</b>
<a>1</z>
========================= ===

...j'obtiens un mauvais résultat:
========================= ===
'<c>3</c>' =~ /<(.*)>(.*)</1>/ trouve $1 = 'c'
'<b>2</b>' =~ /<(.*)>(.*)</1>/ trouve $1 = 'b'
'<a>1</z>' =~ /<(.*)>(.*)</1>/ trouve $1 = '/b'
========================= ===

je vais relire le perlfaq4 comme tu le suggère.


Dans Perlfaq4: "Comment repérer des éléments appariés ou imbriqué s ?",
je pense la passage suivante correspond à ta question:
========================= ===
[...]
++ situant entre deux caractères simples, un motif comme
++ /x([^x]*)x/ mettra les morceaux de l'intervalle dans $1.
++ Lorsque le séparateur est de plusieurs caractères, il
++ faudrait en utiliser un ressemblant plus à /alpha(.*?)omega/.
[...]
========================= ===

On pourrait écrire également:

if (/<([^>]*?)>([^<]*?)</1>/) {

--
Klaus