Einlesen mehrerer Text-Dateien aus einem Ordner
Verfasst von bezNika am 7 Mai, 2009 - 07:32
Hallo,
wie kann ich beim Einlesen von mehreren externen Text-Dateien (aus einem Ordner) (ca. 100) in SAS in EINE SAS-Tabelle den Namen der Text-Datei jeweils ausgeben lassen?
Die SAS-Tabelle sollte nach dem Einlesen folgendermaßen aussehen:
1.Spalte 2.Spalte
Wort1 NameDerTextDatei1
Wort2 NameDerTextDatei1
Wort3 NameDerTextDatei1
.
.
WortN NameDerTextDatei1
Wort1 NameDerTextDatei2
Wort2 NameDerTextDatei2
Wort3 NameDerTextDatei2
.
.
.
»
- Anmelden oder Registrieren um Kommentare zu schreiben

Hi, um in eine SAS-Datei die
Hi,
um in eine SAS-Datei die gewünschten Dateinamen auszulesen brauchen sie drei Schritte.
Als erstes lesen sie sich den Pfadnamen aus, speichern die Anzahl der Elemente in diesem Ordner und speichern nur diese, die auch .txt Dateien sind.
Falls mehrere verschiedene Dateien (.xls, .doc uvm.) enthalten sind, selektieren sie einfach nur die .txt Dateien.
Im folgenden habe ich das so umgesetzt!
%macro txt(path);
%let datasetlist=;
%let rc=%sysfunc(filename(dir, &path));
%let d=%sysfunc(dopen(&dir));
%let n=%sysfunc(dnum(&d));
%do i=1 %to &n;
%let file=%sysfunc(dread(&d, &i));
%if %sysfunc(scan(%sysfunc(lowcase(&file)),2,'.')) eq txt %then %do;
data a&i; length datname $200.; nr=&i; datname="&file"; run;
%let help=&datasetlist;
%let datasetlist=&help a&i;
%end;
%end;
%let rc=%sysfunc(dclose(&d));
data ax; set &datasetlist; run;
proc datasets library=work nodetails nolist; delete a1-a%eval(&n-1); run; quit;
%mend txt;
%txt(C:\Test);
Vielleicht ist das etwas für Sie.
Beste Grüße
Niko
Hallo ,ich würde zuerst das
Hallo ,
ich würde zuerst das Verzeichnis auslesen:
%let pfad1="hier steht der pfad";
filename out pipe "dir &pfad1 /B/A:-D";
data content;
length file $200. ;
infile out length=linelen; ;
input file $Varying500. linelen;
run;
in der Datei Out stehen in der Spalte file die Namen der in Pfad enthaltenen Text-dateien.
Falls es in dem Pfad noch andere Dateien gibt müssten Sie die Spalte file auf die Einträge mit der Endung txt
eingrenzen.
Danach können Sie in einer Makroschleife alle Textdateien einlesen. Etwa wie folgt habe ich es für EXCEL-Tabellen gelöst, wobei ich einen Step zum Einfügen des Namens hinzugefügt habe.
Vielleicht können Sie dieses Programm auf ihren Fall (txt-Dateien) selbst modifizieren:
%macro import(Zieltab=);
%local i anz;
%macro attrn(ds,attrib);
%local dsid rc;
%let dsid=%sysfunc(open(&ds,is));
%if &dsid EQ 0 %then %do;
%put ERROR: (attrn) Dataset &ds not opened due to the following reason:;
%put %sysfunc(sysmsg());
%end;
%else %do;
%sysfunc(attrn(&dsid,&attrib))
%let rc=%sysfunc(close(&dsid));
%end;
%mend;
%macro nobs(ds);
%local nobs;
%let nobs = %attrn(&ds,nobs);
%if &nobs LT 0 %then %let nobs=0;
&nobs
%mend;
%let anz=%nobs(content);
%if &anz ne 0 %then %do;
%do i=1 %to &anz;
DATA _NULL_;
set content (firstobs=&i obs=&i);
Call Execute("PROC IMPORT OUT= WORK.IMP");
Call Execute('DATAFILE="'||"&pfad1\"||compress(file)||'"');
Call Execute('DBMS=EXCEL REPLACE;SHEET="Tabelle1$";GETNAMES=YES; MIXED=YES;SCANTEXT=YES;USEDATE=YES;SCANTIME=YES;RUN;');
/*Für ihr Problem hinzufügen des Namens ggf noch ein lngth Befehl für name setzen!*/
Call Execute("DATA imp; set imp;");
Call Execute("name='"||compress(file)||"';run;");
run;
run;
Proc append base=gesamt data =imp ;
run;
PROC DATASETS lib=WORK NOLIST;
DELETE imp satz;
quit;
%end;
%end;
%mend;
%import;
Hallo, erstmal vielen Dank
Hallo, erstmal vielen Dank für Ihre Hilfe.
Es ist mir aber ehrlich gesagt zu kompliziert :(
Vielleicht kann man alle Text-dateien aus dem Ordner in unterschiedliche SAS-Tabellen importieren?
Ich vermute, danach wäre es etwas einfacher, die Namen von den Dateien einzulesen.
noch einfacher
Hallo,
so geht es auch mit Sonderzeichen und Leerzeichen im Pfad.
Dies Beispiel funktioniert unter Windows. Die temporäre Datei ist nötig, da das INFILE Statement keine Option Encoding verträgt, wenn man als Infile eine PIPE verwendet. Dann muss man erst die Sonderzeichen ersetzen. Da die Macrovariablen nur in Anführungszeichen aufgelöst werden, aber nicht in Hochkommatas, müssen die doppelten Anführungszeichen beim X - Command sein.
%LET PFAD =.\Eigene Dateien;
/*Temporäre Datei definieren */
%LET TEMPDIR = C:\temp\dir.txt;
/*
Dateiliste in Temporäre Datei einlesen
Pfade müssen in Anführungszeichen gesetzt werden
wenn sie Leerzeichen enthalten
Anführungszeichen müssen doppelt angegeben werden, wenn
sie in Anführungszeichen stehen
*/
OPTION NOXWAIT;
X "dir ""&PFAD.\*.txt"" /B /A:-D > ""&TempDir.""" ;
/* Einlesen der temporären Datei */
DATA Dateien;
FORMAT File $256.;
INFILE
"&TempDir."
LENGTH = filelen /* für $Varying. */
/*
DOS verendet einen anderen Zeichensatz als Windows
Wenn die Dateinamen Sonderzeichen enthalten
gibt es sonst Probleme
*/
ENCODING = PCOEM
;
INPUT File $VARYING. filelen;
RUN;
/* Löschen der temporären Datei */
X "delete ""&TempDir.""";
/* Trennzeichen Definieren */
%LET trenner = ' ,;.?!"%&/\=$§+*~#|<>:@()[]{}^° '; /* z. B. */
/* Einlesen aus den Dateien */
DATA woerter;
LENGTH Datei wort $256;
SET dateien;
/* Vollständigen Pfad erzeugen */
Datei=CATS("&PFAD.\", file);
INFILE
Datei
FILEVAR = Datei
DLM = &Trenner.
/* Zu diesem Label wird am Dateiende gesprungen */
EOF = ende
/* Pufferlänge für eine Zeile */
LRECL = 32767
;
/* Datensatz für Datensatz aus Textdatei auslesen*/
DO WHILE (1); /* immer wahr */
Input wort@@; /* Einlesen eines Worts */
/* ... weitere Programmschritte */
OUTPUT; /* Ausgeben des Datensatzes */
END;
/*
Hierhin springt das Programm
wenn das Dateiende erreicht ist
*/
ENDE:
RUN;
Innerhalb der Schleife stehen dann dieselben Befehle, wie wenn man eine einzelne Datei einlesen würde (siehe vorige Frage von Ihnen).
schöne Grüße
Jan
Einfacher So?:
Hallo ,
vielleicht probieren Sie folgendes Makro. Bitte bei dem Pfad und den Namen der Textdateien keine Sonderzeichen und Leerzeichen verwenden sonst sind Anpassungen nötig:
%let pfad1=J:\zzz\bbb\text;
filename out pipe "dir &pfad1 /B/A:-D";
data content;
length file $200. ;
infile out length=linelen; ;
input file $Varying500. linelen;
run;
%macro import(Zieltab=);
Proc SQL noprint;
select distinct file into :lst
separated by "#"
from content;
quit;
%let i=1;
%let dat=%scan(&lst,&i,#);
%do %while (&dat ne );
data WORK._t&i ; ;
%let _EFIERR_ = 0; /* set the ERROR detection macro variable */
infile "&pfad1.\&dat." MISSOVER DSD lrecl=32767 firstobs=2 ;
informat u $1. ;
format u $1. ;
input
u $
;
if _ERROR_ then call symputx('_EFIERR_',1); /* set ERROR detection macro variable */
run;
Data _T&i;
set _T&i;
length name $32.;
name="&dat";
run;
%let i=%eval(&i+1);
%let dat=%scan(&lst,&i,#);
%end;
%mend;
%import;
funktioniert das Makro auch unter UNIX ?
... hab das mal versucht.
filename out pipe "dir &pfad1 /B/A:-D";
data content;
length file $200. ;
infile out length=linelen; ;
input file $Varying500. linelen;
run;
und bekomme "/bin/ksh: dir: not found".
Ich würde gerne ein Verzeichnis auslesen und zwar nur csv files, die mit bestimmten Namen beginnen. Da ich tgl. eine Datei erhalten, wollte ich dann jeweils immer die letzte importieren. dafür würde ich das Verzeichnis auslesen absteigend sortieren und dann die letzte datei importieren.
Nur das Auslesen des UNIX Pfades klappt nicht. Hat jemand noch eine Idee ?
Gruß, Sven
hab den Befehl gefunden...
LS
filename out pipe "ls &pfad1";
data content;
length file $200. ;
infile out length=linelen; ;
input file $Varying500. linelen;
run;
Danach nur noch sortieren und den ersten Wert nehmen.
Sortieren, aber wonach
Hallo,
wonach soll denn sortiert werden?
Wenn es heißt wollte ich dann jeweils immer die letzte importieren, dann denke ich bei die letzte an die jüngste Datei. Also müßte dann nach Datei-Datum sortiert werden ... Bloß: Das fehlt in den eingelesenen Daten ... :-/
Oder man läßt sich die Date-Liste vom Betriebssystem nach Zeit sortiert geben:
filename out pipe "ls -t &pfad1"; /* ls-Befehl mit option -t */
/* -t Sorts by time stamp (latest first) instead of by name */
data content;
length file $200. ;
infile out length=linelen; ;
input file $Varying500. linelen;
run;
data _null_;
set content;
if _N_ eq 1 then do;
call symput("Letzte", file);
end;
run;
%put INFO: Letzte=&Letzte.;
Oder man sortiert selbst, dann benötigt man aber auch das Datei-Änderungsdatum und muß den ls-Befehl entsprechend erweitern:
filename out pipe "ls -l &pfad1"; /* ls-Befehl mit option -l */
/* -l Lists in long format, giving mode, ... size in */
/* bytes and time of last modification for each file */
data content;
length file $200. ;
infile out length=linelen; ;
input file $Varying500. linelen;
run;
Das Sortieren gestaltet sich etwas mühsam, denn die Ausgabe in der SAS-Base-Variable
filesieht z.B. so aus:Eine Anmerkung noch zum ursprünglichen Beispiel aus dem Beitrag von en-trust vom 15. Oktober 2009, 09:06.
Der
ls-Befehl sollte für solche Einsatz-Fälle immer mit der Option-1verwendet werden, denn ohne diese Option gibt der ls-Befehl platzsparend mehrere Datei-Namen in einer Zeile aus, ungefähr so:Mit
ls -1sieht es so aus:Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)