Veröffentlicht am :
ETL CREATION_INTERNE

Lesen und Korrigieren von getrennten Daten mit fehlenden Trennzeichen

Dieser Code ist auch verfügbar auf: English Español Français
Wartet auf Validierung
Das Hauptziel dieses Skripts ist es, Strategien für ein häufiges Problem beim Importieren von Flatfiles bereitzustellen: fehlende Trennzeichen. Das Skript erstellt zunächst eine temporäre Textdatei ('C:\TEMP\osbbb.txt'), die absichtlich Zeilen mit fehlenden Trennzeichen enthält. Anschließend versucht es, diese Datei mit einer Standard-INFILE-Anweisung zu lesen, wobei die daraus resultierenden Fehler (Spaltenverschiebung) demonstriert werden. Schließlich werden zwei korrigierende Ansätze innerhalb eines DATA steps vorgeschlagen: ein erster, der die SAS©-Funktionen FIND und SUBSTR mit der automatischen Variable _INFILE_ verwendet, und ein zweiter, prägnanterer, der die Funktion PRXCHANGE mit einem regulären Ausdruck nutzt, um fehlende Trennzeichen vor dem endgültigen Lesen einzufügen.
Datenanalyse

Type : CREATION_INTERNE


Die Daten werden direkt im Skript über einen DATA _NULL_ step generiert, der eine getrennte Textdatei mit absichtlich fehlenden Trennzeichen schreibt. Diese temporäre Datei wird dann als Quelle für die DATA steps zum Lesen und Korrigieren verwendet.

1 Codeblock
DATA STEP Data
Erklärung :
Dieser Block initialisiert eine Dateireferenz (FILENAME) zu einer Textdatei namens 'osbbb.txt' in 'C:\TEMP'. Anschließend wird ein DATA _NULL_ step verwendet, um Datenzeilen in diese Datei zu erstellen und zu schreiben. Der Inhalt umfasst eine Kopfzeile und mehrere Datenzeilen, von denen einige absichtlich fehlende Trennzeichen enthalten (z. B. fehlt 'Gannet~22JUL2018~Y' das zweite Trennzeichen zwischen 'Gannet' und '22JUL2018'), wodurch ein Szenario mit beschädigten Daten für die folgenden Tests simuliert wird.
Kopiert!
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 Codeblock
DATA STEP Data
Erklärung :
Dieser DATA step versucht, die zuvor erstellte Datei 'MISSING' zu lesen. Die INFILE-Anweisung verwendet das Tilde-Trennzeichen (~), die Option DSD zur Behandlung aufeinanderfolgender Trennzeichen als fehlende Werte, FIRSTOBS=2 zum Ignorieren des Headers und TRUNCOVER, um Fehler zu vermeiden, wenn Zeilen kürzer als erwartet sind. Aufgrund der fehlenden Trennzeichen, die keine aufeinanderfolgenden Trennzeichen, sondern Verschiebungen sind, zeigt dieser Block jedoch, dass das Lesen für die beschädigten Datensätze fehlschlägt, was zu falsch zugewiesenen oder abgeschnittenen Daten führt.
Kopiert!
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 Codeblock
DATA STEP Data
Erklärung :
Dieser DATA step bietet eine erste Lösung zur Korrektur fehlender Trennzeichen. Die Anweisung 'input @;' liest die gesamte Zeile in die automatische Variable _INFILE_ ein, ohne sie zu analysieren. Anschließend wird die Funktion SCAN verwendet, um den angenommenen Inhalt der vierten Spalte ('field4') zu überprüfen. Wenn 'field4' weder 'Y' noch 'N' ist, deutet dies auf ein fehlendes Trennzeichen hin. In diesem Fall findet der Code das erste Trennzeichen (FIND) und fügt ein zusätzliches Tilde ('~') danach ein, indem die Zeichenfolge _INFILE_ mit SUBSTR manipuliert wird. Schließlich liest eine zweite INPUT-Anweisung die korrigierte Zeile aus _INFILE_ für eine korrekte Analyse. Die temporären Variablen DLM1AT und field4 werden anschließend gelöscht (DROP).
Kopiert!
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 Codeblock
DATA STEP Data
Erklärung :
Dieser DATA step bietet eine elegantere und prägnantere Lösung unter Verwendung regulärer Ausdrücke. Wie im vorherigen Block liest 'input @;' die gesamte Zeile in _INFILE_ ein. Die Funktion PRXCHANGE wird dann verwendet, um ein bestimmtes Muster zu suchen: den Zeilenanfang, gefolgt von einer Sequenz von 1 bis 8 Nicht-Tilde-Zeichen, dann eine Tilde, wobei alles in die erste Erfassungsgruppe (\1) erfasst wird. Anschließend wird ein Nicht-Tilde-Zeichen unmittelbar nach der ersten Erfassungsgruppe (\2) gesucht. Wenn dieses Muster gefunden wird (was ein fehlendes Trennzeichen zwischen dem ersten und zweiten Feld signalisiert), wird eine Tilde zwischen die beiden Erfassungsgruppen eingefügt (\1~\2), wodurch _INFILE_ korrigiert wird. Die korrigierte Zeile wird dann von der abschließenden INPUT-Anweisung gelesen.
Kopiert!
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;
Dieses Material wird von We Are Cas "wie besehen" zur Verfügung gestellt. Es gibt keine ausdrücklichen oder stillschweigenden Garantien hinsichtlich der Marktgängigkeit oder Eignung für einen bestimmten Zweck in Bezug auf die hierin enthaltenen Materialien oder Codes. We Are Cas ist nicht verantwortlich für Fehler in diesem Material, wie es jetzt existiert oder existieren wird, noch bietet We Are Cas technischen Support dafür an.
Urheberrechtsinformationen : 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