Substitution et traduction


Tant à savoir identifier des expressions régulières, le Perl sait aussi effectuer des substitutions basées sur ces expressions. On peut donc le faire avec la fonction s, qui est prévue pour simuler le mode de remplacement de l'éditeur vi. Encore une fois, on utilise l'opérateur d'appariement =~ et encore une fois, si la variable de substitution par défaut est $_.

Pour remplacer une occurence du mot paris par Paris, dans la chaîne $phrase, on utilise l'expression:

$phrase =~ s/paris/Paris/
 

et avec la variable $_ cela donne :

s/paris/Paris/

Notez bien que les deux expressions régulières ( paris et Paris) sont encadrées par un total de trois slash. Le résultat de cette expression est le nombre de substitution effectuées, à savoir 0 (aucune) ou 1 (substitution effectuée).


Options

Cet exemple montre seulement le remplacement de la première occurence dans la chaîne, mais il est possible qu'il y ait plus d'une occurence dans la chaîne sur laquelle nous travaillons. Pour rendre cette substitution globale, il faut faire suivre le dernier slash par g :

s/paris/Paris/g
 

Encore une fois, le résultat de cette expression est le nombre de substitution effectuées.

Si on veut effectuer la substitution sur des occurences telles que pAris, paRIS, PaRiS, on peut utiliser :

s/[Pp][Aa][Rr][Ii][Ss]/Paris/g
 

mais une méthode plus simple est d'utiliser l'option i, qui rend l'expression insensible à la casse.

s/paris/Paris/gi
 

Cette expression va effectuer une substitution globale, et indépendante de la casse. On peut aussi utiliser l'option i pour les expressions régulières basiques.


Garder la trace des changements

Il est souvent utile de se souvenir des portions de chaînes qui ont été modifiés, car ils peuvent être réutilisés. Ainsi, toutes les modifications sont conservées dans les variables $1,...,$9. Ces chaînes peuvent aussi être utilisé dans l'expression de la substitution même avec \1,...,\9. Par exemple

$_ = "Le Roi soleil";
s/([A-Z])/:\1:/g;
print "$_\n";
 

Dans cet exemple, toutes les lettres majuscules vont être remplacées par des lettres entourées de ":". On aura ":L:e :R:oi soleil". Les variables $1,...,$9 sont en lecture seule : vous ne pouvez pas les modifier.

Essayer cet autre exemple :

if (/(\b.+\b) \1/)
{
	print "Trouvé $1 répétitions\n";
}
 

Cette expression va trouver tous les mots répétés. Chaque \b represent une limite de mot, et .+ correspond à n'importe quelle chaîne non-vide. Ainsi \b.+\b correspond à une chaîne entre deux limites de mots. Cette chaîne est enregistrées par les parenthèses, et affectée à \1 pour l'expression régulière, et à $1, pour le reste du programme.

L'exemple suivant échange le premier et le dernier caractère de la variable $_ :

s/^(.)(.*)(.)$/\3\2\1/
 

^ et $ correspondent respectivement au début et à la fin de la ligne. \1 enregistre le premier caractère, \2 enregistre tout jusqu'à l'avant dernier inclus, et \3 enregistre le dernier caractère. Il ne reste plus qu'à échanger \1 et \3.

Après une recherche, vous pouvez utiliser les variables $` and $& and $' (lecture seule) pour connaître la partie avant la chaîne trouvée, la chaîne trouvée, et la partie après la chaîne trouvée. Par exemple :

$_ = "Le Roi soleil";
/oi/;
 

donnera les égalités suivantes vraies (notez l'opérateur d'égalité entre chaînes).

$` eq "Le R";
$& eq "oi";
$' eq " soleil";
 

Enfin, pour conclure sur le sujet, il est important de savoir que ce qui est entre les / / est interpolé. Par exemple

$cherche = "le";
s/$cherche/xxx/g;
 

remplacera toutes les occurences de le par xxx. Si vous voulez remplacer les occurences de leur, vous ne pouvez pas faire s/$chercheur/xxx/, car le Perl va essayer d'interpoler $chercheur. A la place, il faut mettre la variable entre accolades :

 
$cherche = "le";
s/{$cherche}ur/xxx/g;
 


Traduction

La fonction tr permet le remplacement caractère par caractère. L'expression suivante remplace les a par des e, les b par des d, les c par des f, dans la variable $phrase. tr renvoie le nombre de substitution effectuées :

$phrase =~ tr/abc/edf/
 

La plus part des caractères spéciaux des expressions régulières ne sont pas disponible avec tr. Par exemple, l'expression ci-dessous compte le nombre d'astérisques dans $phrase, et l'affecte à la variable $nombre.

$nombre = ($phrase =~ tr/*/*/);
 

Cependant, le tiret est toujours utilisé dans le sens jusqu'à. Cette expression effectue la mise en majuscule:

tr/a-z/A-Z/;
 


Exercice

Votre programme actuel devrait être capable de compter les lignes d'un fichier, qui contient une chaîne non nulle. Modifiez le, pour qu'il compte les lignes avec un caractère double (lettre ou autre). Modifiez le encore une fois pour qu'il mette les doubles caractères entre parenthèses. Par exemple, on trouvera des lignes comme :

023 Amp, James Wa(tt), Bob Transformer, etc. These pion(ee)rs conducted many
 

Essayez de faire que tous les couples de lettre identique de chaque phrase soit mis entre parenthèse, et pas seuelement le premier de chaque ligne.

Pour rendre le programme plus interesssant, vous pouvez essayer de faire ceci : supposez que votre programme est appelé "compteur_de_ligne". Alors, vous allez l'appeler

./compteur_de_ligne
 

Cependant, si vous l'appelez avec plusieurs arguments

./compteur_de_ligne premier second etc
 

alors les arguments sont placés dans le tableau @ARGV. Dans l'exemple ci-dessus, nous avons $ARGV[0] qui contient premier et $ARGV[1] qui contient second et $ARGV[2] qui contient... Modifiez votre programme pour qu'il accepte un argument et qu'il compte les lignes qui contiennent cet argument. Vous pouvez mettre le numéro de l'occurence entre parenthèses. Par exemple

./compteur_de_ligne le
 

aura comme affichage :

019 But (Le) grand visionnaire de la république fut Charles de Gaul(le) qui
 


Precedent Start Suivant