Aller au contenu

%SCAN

Chercher un texte dans une chaîne

Renvoie la position de la première occurrence d'un texte dans une chaîne, ou 0 s'il n'y figure pas.

Syntaxe

%SCAN(recherché : chaîne)
%SCAN(recherché : chaîne : début)
recherché
Le texte à trouver : un littéral, une zone ou une expression caractère.
chaîne
La chaîne dans laquelle on cherche.
début
Position à partir de laquelle la recherche commence. Par défaut 1. Utile pour trouver l'occurrence suivante.
Résultat
Un entier : la position du premier caractère trouvé (à partir de 1), ou 0 si le texte est introuvable. La casse compte : Lyon et LYON sont deux textes différents.

À quoi ça sert

C'est la fonction de base pour tester si un mot est présent, ou pour savoir où couper une chaîne avant d'appeler %SUBST : l'arobase d'un courriel, le séparateur d'un fichier CSV, un mot-clé dans un message.

Le résultat 0 sert directement de test : if %scan('x' : texte) > 0;.

Exemple 1 : Positions, occurrences suivantes et découpage

**free
// %SCAN : chercher un texte dans une chaine et obtenir sa position.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s adresse varchar(40) inz('12 rue de la Paix, 34000 Montpellier');
dcl-s courriel varchar(40) inz('service.client@dupont-sa.fr');
dcl-s pos   int(10);
dcl-s pos2  int(10);

pos = %scan('rue' : adresse);
snd-msg 'rue           : ' + %char(pos);

// Recherche a partir d'une position : la 2e occurrence de 'a'.
pos = %scan('a' : adresse);
pos2 = %scan('a' : adresse : pos + 1);
snd-msg 'a (1re, 2e)   : ' + %char(pos) + ', ' + %char(pos2);

// La casse compte, et 0 veut dire "introuvable".
snd-msg 'MONTPELLIER   : ' + %char(%scan('MONTPELLIER' : adresse));
snd-msg 'Montpellier   : ' + %char(%scan('Montpellier' : adresse));

// Decouper un courriel autour de l'arobase.
pos = %scan('@' : courriel);
snd-msg 'Utilisateur   : [' + %subst(courriel : 1 : pos - 1) + ']';
snd-msg 'Domaine       : [' + %subst(courriel : pos + 1) + ']';

*inlr = *on;

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

rue           : 4
a (1re, 2e)   : 12, 15
MONTPELLIER   : 0
Montpellier   : 26
Utilisateur   : [service.client]
Domaine       : [dupont-sa.fr]

rue est en position 4. Pour retrouver la deuxième lettre a, on relance la recherche à la position suivant la première (12, puis 15). La recherche respecte la casse : MONTPELLIER donne 0, Montpellier donne 26.

Enfin, la position de l'arobase, combinée à %SUBST, sépare le nom d'utilisateur du domaine.

Exemple 2 : Les blancs de la zone fixe

**free
// %SCAN : les blancs de fin d'une zone fixe font partie du texte cherche.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s ville  varchar(30) inz('Lyon, Brest, Montpellier');
dcl-s cible  char(10)    inz('Brest');
dcl-s cible2 varchar(10) inz('Brest');

snd-msg 'Zone fixe (char 10)  : ' + %char(%scan(cible : ville));
snd-msg 'Avec %trim           : ' + %char(%scan(%trim(cible) : ville));
snd-msg 'Zone variable        : ' + %char(%scan(cible2 : ville));

*inlr = *on;

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

Zone fixe (char 10)  : 0
Avec %trim           : 7
Zone variable        : 7

La zone fixe cible fait 10 caractères : Brest suivi de 5 blancs. %SCAN cherche donc Brest et ses 5 blancs, ne les trouve pas : résultat 0. Avec %TRIM, ou avec une zone variable, on obtient la bonne position, 7.

Le piège

Une zone fixe cherchée telle quelle contient ses blancs de fin. Si la valeur cherchée est dans une zone de 10 caractères et qu'elle en occupe 5, le programme cherche 10 caractères et ne trouve rien (résultat 0, sans aucune erreur). Il faut passer par %TRIM ou déclarer la zone en varchar.

Pensez aussi à la casse : pour une recherche insensible, on passe les deux textes par %UPPER (ou %LOWER) avant de chercher.