Aller au contenu

%SPLIT

Découper une chaîne en morceaux

Découpe un texte selon un ou plusieurs caractères séparateurs et renvoie la liste des morceaux, à parcourir avec FOR-EACH ou à ranger dans un tableau.

Syntaxe

%SPLIT(chaîne)
%SPLIT(chaîne : séparateurs)
chaîne
Le texte à découper.
séparateurs
Facultatif : les caractères qui séparent les morceaux. Chacun des caractères coupe : ',;' coupe sur la virgule et sur le point-virgule. Sans ce paramètre, le séparateur est le blanc.
Résultat
Une liste de chaînes, sans le séparateur. Elle s'utilise dans un FOR-EACH ou s'affecte à un tableau ; %ELEM compte alors les morceaux si le tableau est déclaré avec dim(*auto : n).

À quoi ça sert

Lire une ligne CSV, séparer les mots d'une phrase, découper un chemin ou une liste de paramètres : avant %SPLIT, il fallait une boucle de %SCAN et de %SUBST. Maintenant, un FOR-EACH suffit, et le morceau arrive déjà découpé.

Exemple 1 : Champs d'une ligne, mots, tableau

**free
// %SPLIT : decouper une ligne en morceaux, dans une boucle FOR-EACH ou dans un tableau.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s ligne   varchar(60) inz('Dupont SA;Montpellier;1250.50');
dcl-s phrase  varchar(60) inz('Bernard Transports Brest');
dcl-s morceau varchar(30);
dcl-s champs  varchar(30) dim(*auto : 10);
dcl-s solde   packed(9:2);

// Le separateur est le point-virgule.
for-each morceau in %split(ligne : ';');
  snd-msg 'Champ : [' + morceau + ']';
endfor;

// Sans separateur indique, le blanc est utilise.
for-each morceau in %split(phrase);
  snd-msg 'Mot   : [' + morceau + ']';
endfor;

// Dans un tableau : %ELEM donne ensuite le nombre de morceaux.
champs = %split(ligne : ';');
solde = %dec(champs(3) : 9 : 2);
snd-msg 'Nombre de champs : ' + %char(%elem(champs));
snd-msg 'Solde + 100      : ' + %char(solde + 100);

*inlr = *on;

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

Champ : [Dupont SA]
Champ : [Montpellier]
Champ : [1250.50]
Mot   : [Bernard]
Mot   : [Transports]
Mot   : [Brest]
Nombre de champs : 3
Solde + 100      : 1350.50

La ligne Dupont SA;Montpellier;1250.50 est parcourue champ par champ. Sans séparateur indiqué, la phrase Bernard Transports Brest est coupée sur les blancs.

Dans un tableau déclaré dim(*auto : 10), on affecte directement %SPLIT. %ELEM donne 3, et le troisième champ se convertit avec %DEC.

Exemple 2 : Champs vides, blancs, tableau trop petit

**free
// %SPLIT : champs vides ignores, blancs conserves, tableau trop petit.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s morceau varchar(30);
dcl-s nb      int(10);
dcl-s petit   varchar(30) dim(2);

// 1. Deux separateurs de suite : le champ vide disparait, les positions sont decalees.
nb = 0;
for-each morceau in %split('100;;Lyon' : ';');
  nb += 1;
  snd-msg 'Vide ignore ' + %char(nb) + ' : [' + morceau + ']';
endfor;

// 2. Avec un blanc entre les separateurs, le champ est conserve.
nb = 0;
for-each morceau in %split('100; ;Lyon' : ';');
  nb += 1;
  snd-msg 'Un blanc    ' + %char(nb) + ' : [' + morceau + ']';
endfor;

// 3. Les blancs autour d'un champ ne sont pas retires.
for-each morceau in %split('a; b ;c' : ';');
  snd-msg 'Espaces       : [' + morceau + ']';
endfor;

// 4. Plusieurs caracteres separateurs : chacun coupe.
nb = 0;
for-each morceau in %split('a,b;c' : ',;');
  nb += 1;
endfor;
snd-msg 'Virgule et point-virgule : ' + %char(nb) + ' morceaux';

// 5. Chaine vide : aucun tour de boucle.
nb = 0;
for-each morceau in %split('' : ';');
  nb += 1;
endfor;
snd-msg 'Chaine vide : ' + %char(nb) + ' tour de boucle';

// 6. Tableau trop petit : le surplus est perdu, sans erreur.
petit = %split('a,b,c' : ',');
snd-msg 'Tableau de 2 : [' + petit(1) + '] [' + petit(2) + ']';

*inlr = *on;

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

Vide ignore 1 : [100]
Vide ignore 2 : [Lyon]
Un blanc    1 : [100]
Un blanc    2 : [ ]
Un blanc    3 : [Lyon]
Espaces       : [a]
Espaces       : [ b ]
Espaces       : [c]
Virgule et point-virgule : 3 morceaux
Chaine vide : 0 tour de boucle
Tableau de 2 : [a] [b]

Six cas de découpe. Dans 100;;Lyon, le champ vide n'apparaît pas : la boucle ne fait que deux tours et Lyon se retrouve en deuxième position. Si le champ contient un blanc (100; ;Lyon), il est conservé.

Les blancs autour d'un champ restent ( b ). Avec deux caractères séparateurs, chacun coupe. Une chaîne vide ne donne aucun tour. Enfin, une affectation dans un tableau de 2 éléments ne garde que a et b, sans erreur.

Le piège

Les champs vides disparaissent. %SPLIT('100;;Lyon' : ';') renvoie deux morceaux, 100 et Lyon, et non trois. Pour un fichier CSV où une colonne peut être vide, la position ne veut plus rien dire : la ville se retrouve dans la colonne du courriel. Il faut soit remplacer les champs vides par un blanc avant le découpage, soit lire le texte avec %SCAN.

Deux autres surprises : les blancs autour des morceaux ne sont pas retirés (utilisez %TRIM), et un tableau trop petit reçoit le début de la liste sans message d'erreur, le reste est perdu.