Aller au contenu

%XLATE

Remplacer des caractères un à un

Remplace chaque caractère d'une liste par le caractère de même rang dans une seconde liste ; les autres caractères ne changent pas.

Syntaxe

%XLATE(de : vers : chaîne)
%XLATE(de : vers : chaîne : départ)
de
La liste des caractères à remplacer, par exemple '.-'.
vers
La liste des caractères de remplacement, dans le même ordre : le premier caractère de de devient le premier de vers, et ainsi de suite.
chaîne
Le texte à transformer.
départ
Facultatif : la position à partir de laquelle on transforme. Les caractères qui précèdent restent intacts. Par défaut, 1.
Résultat
Une chaîne de la même longueur que le texte d'origine, dont les caractères présents dans la liste de ont été remplacés. La zone d'origine n'est pas modifiée.

À quoi ça sert

%XLATE traite d'un coup tous les caractères d'un même type : remplacer les points d'un numéro de téléphone par des espaces, les tirets d'une date par des barres, un séparateur CSV par un autre, ou passer les 26 lettres en majuscules avec deux constantes.

C'est la bonne fonction quand le remplacement se fait caractère par caractère ; pour remplacer un mot par un autre, on utilise %SCANRPL ou %REPLACE.

Exemple 1 : Séparateurs, casse, espaces

**free
// %XLATE : remplacer des caracteres par d'autres, position par position.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s tel   varchar(20) inz('04.67.12.34.56');
dcl-s jour  varchar(10) inz('2026-09-30');
dcl-s ligne varchar(40) inz('100;Dupont SA;Montpellier');
dcl-s nom   varchar(20) inz('martin et fils');
dcl-c MIN 'abcdefghijklmnopqrstuvwxyz';
dcl-c MAJ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';

snd-msg 'Telephone : [' + %xlate('.' : ' ' : tel) + ']';
snd-msg 'Date      : [' + %xlate('-' : '/' : jour) + ']';
snd-msg 'CSV       : [' + %xlate(';' : ',' : ligne) + ']';
snd-msg 'Majuscule : [' + %xlate(MIN : MAJ : nom) + ']';
snd-msg 'Espaces   : [' + %xlate(' ' : '_' : nom) + ']';

*inlr = *on;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

Telephone : [04 67 12 34 56]
Date      : [2026/09/30]
CSV       : [100,Dupont SA,Montpellier]
Majuscule : [MARTIN ET FILS]
Espaces   : [martin_et_fils]

Un seul caractère à remplacer : le point devient un espace dans 04.67.12.34.56, le tiret devient une barre dans la date, le point-virgule devient une virgule dans la ligne CSV.

Avec les deux constantes abc…z et ABC…Z, on obtient des majuscules. Le dernier exemple met des soulignés à la place des espaces : martin_et_fils.

Exemple 2 : Masquer des chiffres, et chaîne « vers » trop courte

**free
// %XLATE : chaine "vers" trop courte, position de depart, resultat en zone fixe.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s carte  varchar(20) inz('4970-1234-5678');
dcl-s fixe   char(20);
dcl-c CHIFFRES '0123456789';

// Piege : une seule lettre dans la chaine "vers", donc seul le 0 est remplace.
snd-msg 'Vers trop courte : [' + %xlate(CHIFFRES : '#' : carte) + ']';
// Correct : autant de caracteres "vers" que de caracteres "de".
snd-msg 'Vers complete    : [' + %xlate(CHIFFRES : '##########' : carte) + ']';
// Position de depart : on garde les 5 premiers caracteres, on masque la suite.
snd-msg 'Depart en 6      : [' + %xlate(CHIFFRES : '##########' : carte : 6) + ']';
// Le resultat prend la longueur de la zone qui le recoit.
fixe = %xlate('-' : ' ' : carte);
snd-msg 'Zone fixe        : [' + fixe + ']';

*inlr = *on;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

Vers trop courte : [497#-1234-5678]
Vers complete    : [####-####-####]
Depart en 6      : [4970-####-####]
Zone fixe        : [4970 1234 5678      ]

Pour masquer les chiffres d'un numéro de carte, la liste vers doit avoir autant de caractères que la liste de. Avec un seul # pour dix chiffres, seul le 0 est remplacé : 4970-1234-5678 devient 497#-1234-5678.

La position de départ garde les cinq premiers caractères (4970-). Enfin, le résultat prend la longueur de la zone qui le reçoit : dans un char(20), le texte est complété par des blancs.

Le piège

Une liste « vers » plus courte n'efface rien et ne complète pas. Les caractères de de qui n'ont pas de vis-à-vis dans vers restent tels quels. On croit masquer tous les chiffres avec %XLATE('0123456789' : '#' : carte) ; on masque seulement les zéros.

Deuxième surprise : %XLATE ne supprime pas de caractères et ne change pas la longueur. Il ne peut pas retirer les tirets d'un numéro (pour cela, %SCANRPL). Et une table a-z vers A-Z laisse les lettres accentuées : Café devient CAFé (voir l'exemple 2 de %UPPER). Pour les accents, utilisez %UPPER.