OVH Cloud OVH Cloud

substituer un mot redondant dans une ligne ?

4 réponses
Avatar
ctobini
Bonjour,

J'ai un petit probl=E8me avec les regex :

Je voudrais faire une subsitution sur les patterns redondants dans les
lignes d'un fichier, mais ces patterns peuvent =EAtres repr=E9sent=E9s
avec une fr=E9quence non fixe :

;pattern;pattern;mot;mot;pattern;
;pattern;mot;mot;pattern;

Je voudrais subsituer chaque occurence de 'pattern' contre par exemple
'chemin' dans chaque ligne.

En faisant s/pattern/chemin/g il n'y a que le premier 'pattern' qui est
substitu=E9 pour chaque ligne.

Sauriez-vous comment faire ?

Merci.

C=2E Tobini

4 réponses

Avatar
Paul Gaborit
À (at) 24 Jan 2006 07:34:50 -0800,
"ctobini" écrivait (wrote):
Je voudrais faire une subsitution sur les patterns redondants dans les
lignes d'un fichier, mais ces patterns peuvent êtres représentés
avec une fréquence non fixe :

;pattern;pattern;mot;mot;pattern;
;pattern;mot;mot;pattern;

Je voudrais subsituer chaque occurence de 'pattern' contre par exemple
'chemin' dans chaque ligne.


Ok.

En faisant s/pattern/chemin/g il n'y a que le premier 'pattern' qui est
substitué pour chaque ligne.


En êtes-vous sûr ? Normalement, le 'g' sert justement à indiquer qu'on
veut remplacer *toutes* les occurences...

Sauriez-vous comment faire ?


Montrez-nous du code... L'erreur est ailleurs !

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

Avatar
ctobini
Bonjour et merci de la réponse,

Le code est du style :
while (<>) {
if (/pattern/) {
s/pattern/chemin/g;
}
}

Je pense que le if vérifie si la ligne contient au moins une fois
'pattern' et la substitution devrait agir ensuite en global sur la
ligne.

J'ai néanmoins trouvé une solution :

s/pattern/chemin/ while /pattern/;

J'aimerais tout de même comprendre où se situe le problème avec
s///g.

Merci.

C. Tobini
Avatar
Paul Gaborit
À (at) 24 Jan 2006 10:07:37 -0800,
"ctobini" écrivait (wrote):
Le code est du style :
while (<>) {
if (/pattern/) {
s/pattern/chemin/g;
}
}

Je pense que le if vérifie si la ligne contient au moins une fois
'pattern' et la substitution devrait agir ensuite en global sur la
ligne.


C'est exactement cela...

J'ai néanmoins trouvé une solution :

s/pattern/chemin/ while /pattern/;


Dans la plupart des cas, ça devrait être équivalent...

J'aimerais tout de même comprendre où se situe le problème avec
s///g.


Nous aussi ... ;-)

Exemple :

my $ligne = "le leton est aller a l'etale.";
$ligne =~ s/le/LE/g;
print "$lignen";

qui donne bien le résultat attendu :

LE LEton est alLEr a l'etaLE.

Un cas qui peut rendre les deux écritures non équivalentes est celui
où le motif (pattern) est reconnu sur des chaînes qui se
chevauchent. Exemple :

my ($t1, $t2) = ("radar") x 2;

$t1 =~ s/(w)(w{1,3})1/$1--$2--$1/g;

while ($t2 =~ m/(w)(w{1,3})1/) {
$t2 =~ s/(w)(w{1,3})1/$1--$2--$1/;
}
print "t1: $t1n";
print "t2: $t2n";

qui donne :

t1: r--ada--r
t2: r--a--d--a--r

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

Avatar
Martin
Allo,

J'ai néanmoins trouvé une solution :
s/pattern/chemin/ while /pattern/;
J'aimerais tout de même comprendre où se situe le problème avec
s///g.


Je fais l'hypothèse que ton pattern n'est présent qu'une fois probablement à
cause d'une erreur d'inattention du genre d'un ^ en début ou d'un $ en fin
de regexp. Après la première application de la substitution, le pattern peut
être retrouvé à nouveau.