Publié le :
ETL CREATION_INTERNE

Lecture et correction de données délimitées avec délimiteurs manquants

Ce code est également disponible en : Deutsch English Español
En attente de validation
L'objectif principal de ce script est de fournir des stratégies pour un problème courant lors de l'importation de fichiers plats : les délimiteurs manquants. Le script crée d'abord un fichier texte temporaire ('C:\TEMP\osbbb.txt') contenant volontairement des lignes avec des délimiteurs manquants. Ensuite, il tente de lire ce fichier avec une instruction INFILE standard, démontrant les erreurs qui en découlent (décalage des colonnes). Enfin, il propose deux approches correctives au sein d'un DATA step : une première utilisant les fonctions SAS© FIND et SUBSTR avec la variable automatique _INFILE_, et une seconde, plus concise, exploitant la fonction PRXCHANGE avec une expression régulière pour insérer les délimiteurs manquants avant la lecture finale.
Analyse des données

Type : CREATION_INTERNE


Les données sont générées directement dans le script via un DATA _NULL_ step, qui écrit un fichier texte délimité avec des délimiteurs manquants intentionnels. Ce fichier temporaire est ensuite utilisé comme source pour les DATA steps de lecture et de correction.

1 Bloc de code
DATA STEP Data
Explication :
Ce bloc initialise une référence de fichier (FILENAME) vers un fichier texte nommé 'osbbb.txt' dans 'C:\TEMP'. Ensuite, un DATA _NULL_ step est utilisé pour créer et écrire des lignes de données dans ce fichier. Le contenu inclut une ligne d'en-tête et plusieurs lignes de données, dont certaines ont intentionnellement des délimiteurs manquants (par exemple, 'Gannet~22JUL2018~Y' manque le deuxième délimiteur entre 'Gannet' et '22JUL2018'), simulant ainsi un scénario de données corrompues pour les tests suivants.
Copié !
1FILENAME MISSING 'C:\TEMP\osbbb.txt';
2 
3DATA _NULL_;
4 file MISSING;
5 put 'Animal~Mode~Date~Bird';
6 put 'Beaver~~09OCT2019~N';
7 put 'Gannet~22JUL2018~Y';
8 * ^-- missing delimiter;
9 put 'Peacock~~17DEC2017~Y';
10 put 'Robin~23FEB2019~Y';
11 * ^-- missing delimiter;
12 put 'Nuthatch~19APR2019~Y';
13 * ^-- missing delimiter;
14RUN;
2 Bloc de code
DATA STEP Data
Explication :
Ce DATA step tente de lire le fichier 'MISSING' créé précédemment. L'instruction INFILE utilise le délimiteur tilde (~), l'option DSD pour traiter les délimiteurs consécutifs comme des valeurs manquantes, FIRSTOBS=2 pour ignorer l'en-tête, et TRUNCOVER pour empêcher les erreurs lorsque les lignes sont plus courtes que prévu. Cependant, en raison des délimiteurs manquants qui ne sont pas des délimiteurs consécutifs mais des décalages, ce bloc démontre que la lecture échouera pour les enregistrements corrompus, entraînant des données incorrectement assignées ou tronquées.
Copié !
1DATA missing;
2 INFILE MISSING dlm='~' DSD firstobs=2 truncover;
3 FORMAT Animal $8. Mode $5. Date DATE9. Bird $1.;
4 INPUT Animal Mode Date:DATE9. Bird;
5RUN;
3 Bloc de code
DATA STEP Data
Explication :
Ce DATA step propose une première solution pour corriger les délimiteurs manquants. L'instruction 'input @;' lit la ligne complète dans la variable automatique _INFILE_ sans l'analyser. Il utilise ensuite la fonction SCAN pour vérifier le contenu supposé de la quatrième colonne ('field4'). Si 'field4' n'est pas 'Y' ou 'N', cela indique un délimiteur manquant. Dans ce cas, le code trouve le premier délimiteur (FIND) et insère un tilde ('~') supplémentaire après celui-ci en manipulant la chaîne _INFILE_ avec SUBSTR. Enfin, une seconde instruction INPUT relit la ligne corrigée à partir de _INFILE_ pour un parsing correct. Les variables temporaires DLM1AT et field4 sont ensuite supprimées (DROP).
Copié !
1DATA fixed (drop=DLM1AT field4);
2 INFILE MISSING dlm='~' DSD firstobs=2;
3 FORMAT Animal $8. Mode $5. Date DATE9. Bird $1.;
4 INPUT @;
5 LENGTH field4 $1;
6 field4 = scan(_INFILE_, 4, '~', 'M');
7 IF field4 not in ('Y', 'N') THEN DO;
8 DLM1AT = FIND(_INFILE_, '~');
9 _INFILE_ = SUBSTR(_INFILE_, 1, DLM1AT) ||
10 '~' || SUBSTR(_INFILE_, DLM1AT + 1);
11 END;
12 INPUT Animal Mode Date:DATE9. Bird;
13RUN;
4 Bloc de code
DATA STEP Data
Explication :
Ce DATA step offre une solution plus élégante et concise en utilisant les expressions régulières. Comme le bloc précédent, 'input @;' lit la ligne complète dans _INFILE_. La fonction PRXCHANGE est ensuite utilisée pour rechercher un motif spécifique : le début de la chaîne, suivi d'une séquence de 1 à 8 caractères non-tilde, puis un tilde, capturant le tout dans le premier groupe de capture (\1). Il recherche ensuite un caractère non-tilde immédiatement après le premier groupe de capture (\2). Si ce motif est trouvé (ce qui signale un délimiteur manquant entre le premier et le deuxième champ), il insère un tilde entre les deux groupes de capture (\1~\2), corrigeant ainsi _INFILE_. La ligne corrigée est ensuite lue par l'instruction INPUT finale.
Copié !
1DATA everythings_better_with_regex;
2 INFILE MISSING dlm='~' DSD firstobs=2;
3 FORMAT Animal $8. Mode $5. Date DATE9. Bird $1.;
4 INPUT @;
5 _INFILE_ = PRXCHANGE('s/^([^~]{1,8}~)([^~])/, 1, _INFILE_);
6 INPUT Animal Mode Date:DATE9. Bird;
7RUN;
Ce matériel est fourni "tel quel" par We Are Cas. Il n'y a aucune garantie, expresse ou implicite, quant à la qualité marchande ou à l'adéquation à un usage particulier concernant le matériel ou le code contenu dans les présentes. We Are Cas n'est pas responsable des erreurs dans ce matériel tel qu'il existe maintenant ou existera, et We Are Cas ne fournit pas de support technique pour celui-ci.
Informations de Copyright : Paper 4839-2020 Read Before You Read: Reading, Rewriting & Re-Reading Difficult Delimited Data in a Data Step Appendix B - Complete Code for Missing Delimiters