-
Notifications
You must be signed in to change notification settings - Fork 8
/
fread.sas
153 lines (126 loc) · 5.65 KB
/
fread.sas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
%macro fread
/*----------------------------------------------------------------------
Read file using only macro code.
----------------------------------------------------------------------*/
(file /* Fileref or path name */
,mode=1 /* Operation Mode */
/* Mode=1 returns macro variable array (requires %UNQUOTE()) */
/* Mode=2 puts file contents to SAS log */
/* Mode=3 returns file contents as macro result */
,lineno=0 /* Include line numbers when Mode=2? 0=No 1=Yes */
,eol=| /* Characters to output after each line when MODE=3 */
);
/*----------------------------------------------------------------------
Read a file to (mode=1) local macro variables, (mode=2) the log or
(mode=3) the macro function result. Values will be macro quoted.
MODE=1
------
This will return the lines in the form of a series of %LET statements
to create an array of macro variables (N,W1,W2,....). You will need
to wrap the %FREAD() call inside of %UNQUOTE() to have the macro
variables created in the calling environment.
%unquote(%fred(config.dat))
%do i=1 %to &n ;
%if (&&w&i = YES) %then %let found=1;
%end;
MODE=2
------
Write the file to the SAS log using %PUT statements. Set LINENO=1 to
have the lines prefixed with 5 digit line numbers.
MODE=3
------
Return the file as the result of the macro call. You can use the EOL=
parameter to insert a delimiter string between the lines.
Note files larger than macro variable limit (64K bytes) will not work
with MODE=1 or MODE=3.
Note: This macro requires %FILEREF() macro.
-----------------------------------------------------------------------
This macro was adopted from code developed by Tom Hoffman.
History:
07APR00 TRHoffman Creation
01MAY00 TRHoffman Cleared fileref. Protected length statement against
unmatched parentheses in input file.
03MAY00 TRHoffman Corrected invalid file close.
08MAY00 TRHoffman Added MODE parameter.
2016-08-12 abernt Removed the code that was stripping macro triggers.
Replaced with QUOTE()/DEQUOTE() calls.
Added LINENO and EOL parameters.
----------------------------------------------------------------------*/
%local n filerc fileref fid text rc j sep ;
%*----------------------------------------------------------------------
Initialize line counter.
-----------------------------------------------------------------------;
%let n = 0;
%if %fileref(&file)<=0 %then %do;
%*----------------------------------------------------------------------
When FILE is an existing FILEREF then use it.
-----------------------------------------------------------------------;
%let filerc = 1;
%let fileref=&file;
%end;
%else %if %sysfunc(fileexist(&file)) %then %do;
%*----------------------------------------------------------------------
Create new fileref for the existing file.
-----------------------------------------------------------------------;
%let filerc = %sysfunc(filename(fileref,&file));
%end;
%if %length(&fileref) %then %do;
%*----------------------------------------------------------------------
Open file for streaming input access.
-----------------------------------------------------------------------;
%let fid = %sysfunc(fopen(&fileref,s));
%if (&fid > 0) %then %do;
%*----------------------------------------------------------------------
Write a blank line before the output when MODE=2.
-----------------------------------------------------------------------;
%if (&mode=2) %then %put %str( );
%*----------------------------------------------------------------------
Read through file and process each line.
-----------------------------------------------------------------------;
%do %while(%sysfunc(fread(&fid)) = 0);
%let n = %eval(&n + 1);
%let rc = %sysfunc(fget(&fid,text,32767));
%if (&mode = 1) %then %do;
%*----------------------------------------------------------------------
MODE=1 Store the quoted value into local macro variable.
-----------------------------------------------------------------------;
%local w&n;
%let w&n = %sysfunc(quote(%superq(text),%str(%')));
%end;
%else %if (&mode = 2) %then %do;
%*----------------------------------------------------------------------
MODE=2 Write line to LOG with optional line numbers.
-----------------------------------------------------------------------;
%if ^(&lineno) %then %put %superq(text) ;
%else %put %sysfunc(putn(&n,Z5)) %superq(text) ;
%end;
%else %do;
%*----------------------------------------------------------------------
MODE=3 Return the line with optional end of line string.
-----------------------------------------------------------------------;
%*;&sep.%superq(text)
%let sep=%superq(eol);
%end;
%end;
%*----------------------------------------------------------------------
Write a blank line after the output when MODE=2.
-----------------------------------------------------------------------;
%if (&mode=2) %then %put %str( );
%let rc = %sysfunc(fclose(&fid));
%end;
%*----------------------------------------------------------------------
Clear fileref when assigned by macro,
-----------------------------------------------------------------------;
%if ^(&filerc) %then %let rc = %sysfunc(filename(fileref));
%end;
%if (&mode = 1) %then %do;
%*----------------------------------------------------------------------
Create quoted %let statements to recreate the macro variables.
Use %QSYSFUNC(DEQUOTE()) to remove the quoting added above.
-----------------------------------------------------------------------;
%*;%nrstr(%let )n=&n%str(;)
%do j = 1 %to &n;
%*;%nrstr(%let )w&j=%nrstr(%qsysfunc)(dequote(&&w&j))%str(;)%*;
%end;
%end;
%mend fread;