Je voudrais écrire un script qui échange des chaînes de caractères
dans un fichier texte.
Par exemple, je voudrais que tous les « foo » deviennent des « bar »
tandis que tous les « bar » deviennent des « foo », que tous les
« toto » deviennent des « titi » tandis que tous les « titi »
deviennent des « toto », etc. pour une quinzaine de mots.
Ainsi, le texte :
salut foo titi foo bar
bar bonjour foo bar titi
Deviendrait :
salut bar toto bar foo
foo bonjour bar foo toto
Vu que le texte ne contiendra pas certains caractères, je pourrais
le faire en plusieurs passes. Par exemple une première passe :
foo -> BAR
bar -> FOO
toto -> TITI
titi -> TOTO
Puis une deuxième passe :
BAR -> bar
FOO -> foo
TITI -> titi
TOTO -> toto
Mais existe-t-il une méthode plus efficace ? Idéalement, j'aimerais
bien écrire une seule fois mes deux listes de mots (ou ma liste de
paires de mots).
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Nicolas George
Olivier Miakinen , dans le message <ql350h$2il9$, a écrit :
Mais existe-t-il une méthode plus efficace ? Idéalement, j'aimerais bien écrire une seule fois mes deux listes de mots (ou ma liste de paires de mots).
Si tes chaînes sont bien toutes constantes, tu peux accéder à une table de hachage depuis l'expression de remplacement : s/($re)/$map{$1}/g; Tu peux facilement construire $re à partir de %map : my $re = join("|", sort(keys(%map))); $re = qr/$re/; Je pense que tu es capable de faire le reste. Si les chaînes ne sont pas constantes, tu peux faire pareil si tu as une fonction qui implémente le remplacement individuel, en utilisant le flag e à l'opérateur de remplacement.
Olivier Miakinen , dans le message <ql350h$2il9$1@cabale.usenet-fr.net>,
a écrit :
Mais existe-t-il une méthode plus efficace ? Idéalement, j'aimerais
bien écrire une seule fois mes deux listes de mots (ou ma liste de
paires de mots).
Si tes chaînes sont bien toutes constantes, tu peux accéder à une table
de hachage depuis l'expression de remplacement :
s/($re)/$map{$1}/g;
Tu peux facilement construire $re à partir de %map :
my $re = join("|", sort(keys(%map)));
$re = qr/$re/;
Je pense que tu es capable de faire le reste.
Si les chaînes ne sont pas constantes, tu peux faire pareil si tu as une
fonction qui implémente le remplacement individuel, en utilisant le flag
e à l'opérateur de remplacement.
Olivier Miakinen , dans le message <ql350h$2il9$, a écrit :
Mais existe-t-il une méthode plus efficace ? Idéalement, j'aimerais bien écrire une seule fois mes deux listes de mots (ou ma liste de paires de mots).
Si tes chaînes sont bien toutes constantes, tu peux accéder à une table de hachage depuis l'expression de remplacement : s/($re)/$map{$1}/g; Tu peux facilement construire $re à partir de %map : my $re = join("|", sort(keys(%map))); $re = qr/$re/; Je pense que tu es capable de faire le reste. Si les chaînes ne sont pas constantes, tu peux faire pareil si tu as une fonction qui implémente le remplacement individuel, en utilisant le flag e à l'opérateur de remplacement.
Olivier Miakinen
Le 08/09/2019 17:06, Nicolas George m'a répondu :
Si tes chaînes sont bien toutes constantes,
Tu veux dire si ce ne sont pas des regexp ? Pour le moment elles sont bien toutes constantes, mais je crains de devoir ajouter plus tard des assertions à certaines d'entre elles. Par exemple : "abcd" => "truc" "truc" => "abcd" "abc(?!d)" => "machin" "machin" => "abc"
tu peux accéder à une table de hachage depuis l'expression de remplacement : s/($re)/$map{$1}/g; Tu peux facilement construire $re à partir de %map : my $re = join("|", sort(keys(%map))); $re = qr/$re/; Je pense que tu es capable de faire le reste.
J'ai eu du mal car je ne suis pas encore tout à fait au point en perl, mais en m'aidant de la doc je suis arrivé à ceci : ---------------------------------------------------------------------- #!/usr/bin/perl use strict; use warnings; my %map = ( "foo" => "bar", "toto" => "titi" ); %map = (%map, reverse %map); my $re = join("|", keys(%map)); $re = qr/$re/; my $phrase = " salut foo titi foo barn bar bonjour foo bar titin"; print "Avant :n$phrase"; $phrase =~ s/($re)/$map{$1}/g; print "Après :n$phrase"; ---------------------------------------------------------------------- Avec comme résultat : ---------------------------------------------------------------------- Avant : salut foo titi foo bar bar bonjour foo bar titi Après : salut bar toto bar foo foo bonjour bar foo toto ----------------------------------------------------------------------
Si les chaînes ne sont pas constantes, tu peux faire pareil si tu as une fonction qui implémente le remplacement individuel, en utilisant le flag e à l'opérateur de remplacement.
Ah oui, je crois que je vois ce que c'est. Je vais y réfléchir. Encore merci ! -- Olivier Miakinen
Le 08/09/2019 17:06, Nicolas George m'a répondu :
Si tes chaînes sont bien toutes constantes,
Tu veux dire si ce ne sont pas des regexp ? Pour le moment elles
sont bien toutes constantes, mais je crains de devoir ajouter plus
tard des assertions à certaines d'entre elles.
Par exemple :
"abcd" => "truc"
"truc" => "abcd"
"abc(?!d)" => "machin"
"machin" => "abc"
tu peux accéder à une table
de hachage depuis l'expression de remplacement :
s/($re)/$map{$1}/g;
Tu peux facilement construire $re à partir de %map :
my $re = join("|", sort(keys(%map)));
$re = qr/$re/;
Je pense que tu es capable de faire le reste.
J'ai eu du mal car je ne suis pas encore tout à fait au point en
perl, mais en m'aidant de la doc je suis arrivé à ceci :
----------------------------------------------------------------------
#!/usr/bin/perl
use strict;
use warnings;
my $phrase = " salut foo titi foo barn bar bonjour foo bar titin";
print "Avant :n$phrase";
$phrase =~ s/($re)/$map{$1}/g;
print "Après :n$phrase";
----------------------------------------------------------------------
Avec comme résultat :
----------------------------------------------------------------------
Avant :
salut foo titi foo bar
bar bonjour foo bar titi
Après :
salut bar toto bar foo
foo bonjour bar foo toto
----------------------------------------------------------------------
Si les chaînes ne sont pas constantes, tu peux faire pareil si tu as une
fonction qui implémente le remplacement individuel, en utilisant le flag
e à l'opérateur de remplacement.
Ah oui, je crois que je vois ce que c'est. Je vais y réfléchir.
Tu veux dire si ce ne sont pas des regexp ? Pour le moment elles sont bien toutes constantes, mais je crains de devoir ajouter plus tard des assertions à certaines d'entre elles. Par exemple : "abcd" => "truc" "truc" => "abcd" "abc(?!d)" => "machin" "machin" => "abc"
tu peux accéder à une table de hachage depuis l'expression de remplacement : s/($re)/$map{$1}/g; Tu peux facilement construire $re à partir de %map : my $re = join("|", sort(keys(%map))); $re = qr/$re/; Je pense que tu es capable de faire le reste.
J'ai eu du mal car je ne suis pas encore tout à fait au point en perl, mais en m'aidant de la doc je suis arrivé à ceci : ---------------------------------------------------------------------- #!/usr/bin/perl use strict; use warnings; my %map = ( "foo" => "bar", "toto" => "titi" ); %map = (%map, reverse %map); my $re = join("|", keys(%map)); $re = qr/$re/; my $phrase = " salut foo titi foo barn bar bonjour foo bar titin"; print "Avant :n$phrase"; $phrase =~ s/($re)/$map{$1}/g; print "Après :n$phrase"; ---------------------------------------------------------------------- Avec comme résultat : ---------------------------------------------------------------------- Avant : salut foo titi foo bar bar bonjour foo bar titi Après : salut bar toto bar foo foo bonjour bar foo toto ----------------------------------------------------------------------
Si les chaînes ne sont pas constantes, tu peux faire pareil si tu as une fonction qui implémente le remplacement individuel, en utilisant le flag e à l'opérateur de remplacement.
Ah oui, je crois que je vois ce que c'est. Je vais y réfléchir. Encore merci ! -- Olivier Miakinen
Nicolas George
Olivier Miakinen , dans le message <ql3av3$2k1j$, a écrit :
Tu veux dire si ce ne sont pas des regexp ? Pour le moment elles sont bien toutes constantes, mais je crains de devoir ajouter plus tard des assertions à certaines d'entre elles.
Je n'aurais pas utilisé reverse pour cet usage, mais ça marche.
Ah oui, je crois que je vois ce que c'est. Je vais y réfléchir.
Ce n'est pas très compliqué: sub replace_word($) { my ($in) = $_; return ...; } $text =~ s/($re)/replace_word($1)/ge; Il ne reste qu'à écrire le code de replace_word.
Olivier Miakinen , dans le message <ql3av3$2k1j$1@cabale.usenet-fr.net>,
a écrit :
Tu veux dire si ce ne sont pas des regexp ? Pour le moment elles
sont bien toutes constantes, mais je crains de devoir ajouter plus
tard des assertions à certaines d'entre elles.
Olivier Miakinen , dans le message <ql3av3$2k1j$, a écrit :
Tu veux dire si ce ne sont pas des regexp ? Pour le moment elles sont bien toutes constantes, mais je crains de devoir ajouter plus tard des assertions à certaines d'entre elles.
Je n'aurais pas utilisé reverse pour cet usage, mais ça marche.
Ah oui, je crois que je vois ce que c'est. Je vais y réfléchir.
Ce n'est pas très compliqué: sub replace_word($) { my ($in) = $_; return ...; } $text =~ s/($re)/replace_word($1)/ge; Il ne reste qu'à écrire le code de replace_word.
Olivier Miakinen
Le 08/09/2019 19:34, Nicolas George a écrit :
Tu veux dire si ce ne sont pas des regexp ? Pour le moment elles sont bien toutes constantes, mais je crains de devoir ajouter plus tard des assertions à certaines d'entre elles.
Dans ce cas, il va falloir ruser.
Il faut mettre "abc(?!d)" dans la regexp mais "abc" => "machin" dans le %map. Du coup il y a au moins une chaîne que j'écris deux fois mais ce n'est pas insurmontable. Si je me rends compte plus tard que j'ai besoin d'automatiser le truc, j'aviserai le moment venu.
Je n'aurais pas utilisé reverse pour cet usage, mais ça marche.
Oui. J'ai essayé une syntaxe à base de map() mais je n'y suis pas arrivé. Alors comme reverse() fonctionne j'ai trouvé que c'était le plus simple.
Ah oui, je crois que je vois ce que c'est. Je vais y réfléchir.
Ce n'est pas très compliqué: sub replace_word($) { my ($in) = $_; return ...; } $text =~ s/($re)/replace_word($1)/ge; Il ne reste qu'à écrire le code de replace_word.
Oui, ok. Ça peut être une piste pour automatiser l'histoire des assertions. Merci pour tout, Nicolas. -- Olivier Miakinen
Le 08/09/2019 19:34, Nicolas George a écrit :
Tu veux dire si ce ne sont pas des regexp ? Pour le moment elles
sont bien toutes constantes, mais je crains de devoir ajouter plus
tard des assertions à certaines d'entre elles.
Dans ce cas, il va falloir ruser.
Il faut mettre "abc(?!d)" dans la regexp mais "abc" => "machin" dans
le %map. Du coup il y a au moins une chaîne que j'écris deux fois
mais ce n'est pas insurmontable. Si je me rends compte plus tard que
j'ai besoin d'automatiser le truc, j'aviserai le moment venu.
Tu veux dire si ce ne sont pas des regexp ? Pour le moment elles sont bien toutes constantes, mais je crains de devoir ajouter plus tard des assertions à certaines d'entre elles.
Dans ce cas, il va falloir ruser.
Il faut mettre "abc(?!d)" dans la regexp mais "abc" => "machin" dans le %map. Du coup il y a au moins une chaîne que j'écris deux fois mais ce n'est pas insurmontable. Si je me rends compte plus tard que j'ai besoin d'automatiser le truc, j'aviserai le moment venu.
Je n'aurais pas utilisé reverse pour cet usage, mais ça marche.
Oui. J'ai essayé une syntaxe à base de map() mais je n'y suis pas arrivé. Alors comme reverse() fonctionne j'ai trouvé que c'était le plus simple.
Ah oui, je crois que je vois ce que c'est. Je vais y réfléchir.
Ce n'est pas très compliqué: sub replace_word($) { my ($in) = $_; return ...; } $text =~ s/($re)/replace_word($1)/ge; Il ne reste qu'à écrire le code de replace_word.
Oui, ok. Ça peut être une piste pour automatiser l'histoire des assertions. Merci pour tout, Nicolas. -- Olivier Miakinen