Aller au contenu

%SUBST

Extraire une partie d'une chaîne

Renvoie une portion d'une chaîne à partir d'une position donnée, sur une longueur choisie ou jusqu'à la fin, et peut aussi servir à modifier cette portion.

Syntaxe

%SUBST(chaîne : début)
%SUBST(chaîne : début : longueur)
chaîne
La zone ou l'expression caractère dans laquelle on prélève.
début
Position du premier caractère à prendre (le premier caractère est en position 1).
longueur
Nombre de caractères à prendre. Sans ce paramètre, on prend tout jusqu'à la fin de la chaîne.
Résultat
Une valeur caractère (variable si la chaîne est variable). À gauche du signe égal, %SUBST désigne la portion de la zone, qu'on peut alors remplacer sans toucher au reste.

À quoi ça sert

Une référence, un code postal, une date stockée en texte : les données IBM i sont pleines de champs dont chaque tranche a un sens. %SUBST isole la tranche voulue sans variable de travail ni redéfinition de la zone en structure de données.

Combinée à %SCAN, qui donne la position d'un séparateur, elle permet de découper n'importe quel texte.

Exemple 1 : Extraire et modifier une portion

**free
// %SUBST : extraire une partie d'une chaine (et en modifier une partie).
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s reference char(13) inz('FAC-2026-0417');
dcl-s texte     varchar(20) inz('Dupont SA');
dcl-s annee     char(4);

annee = %subst(reference : 5 : 4);
snd-msg 'Annee       : [' + annee + ']';
snd-msg 'Numero      : [' + %subst(reference : 10) + ']';
snd-msg 'Debut       : [' + %subst(reference : 1 : 3) + ']';
snd-msg 'Variable    : [' + %subst(texte : 8 : 2) + ']';

// %SUBST peut aussi recevoir une valeur (a gauche du =).
%subst(reference : 1 : 3) = 'AVO';
snd-msg 'Modifie     : [' + reference + ']';

*inlr = *on;

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

Annee       : [2026]
Numero      : [0417]
Debut       : [FAC]
Variable    : [SA]
Modifie     : [AVO-2026-0417]

Le premier appel prend 4 caractères à partir de la position 5 : l'année. Sans longueur, %SUBST(reference : 10) va jusqu'au bout. Sur la zone variable, on prend les deux derniers caractères de Dupont SA.

La dernière ligne place %SUBST à gauche du signe égal : seuls les trois premiers caractères de la référence changent.

Exemple 2 : Sortir des limites de la chaîne

**free
// %SUBST hors limites : la zone fixe contient des blancs, la zone variable non.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s fixe  char(10)     inz('Brest');
dcl-s varie varchar(10)  inz('Brest');

// Zone fixe : les 5 derniers caracteres sont des blancs.
snd-msg 'Fixe   : [' + %subst(fixe : 4 : 7) + ']';
snd-msg 'Longueur de la zone variable : ' + %char(%len(varie));
// Zone variable : on depasse la longueur courante (5) -> erreur.
snd-msg 'Varie  : [' + %subst(varie : 4 : 7) + ']';
snd-msg 'Cette ligne ne sera jamais affichee';

*inlr = *on;

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

Fixe   : [st     ]
Longueur de la zone variable : 5
Erreur : RNQ0100 - Longueur ou position de départ hors limites pour opération sur chaîne.

Sur la zone fixe de 10 caractères, prendre 7 caractères à partir de la position 4 fonctionne : les blancs de fin font partie de la zone, on obtient st suivi de cinq blancs.

Sur la zone variable, dont la longueur courante est 5, la même demande dépasse la fin : le programme s'arrête avec l'erreur RNQ0100 (RNX0100 dans le journal du travail) et la dernière ligne n'est jamais affichée.

Le piège

Dépasser la longueur courante est une erreur d'exécution. Le compilateur ne dit rien, mais si début + longueur - 1 dépasse la longueur de la chaîne, le programme s'interrompt avec RNX0100. Le piège vient surtout des zones variables : leur longueur change avec le contenu, alors qu'une zone fixe garde toujours sa taille déclarée (avec des blancs).

Avant un %SUBST dont la position dépend des données, on teste donc la longueur avec %LEN. Attention au résultat de %SCAN : il vaut 0 quand le texte est introuvable, et %SUBST(x : 0) provoque la même erreur RNX0100.