I have the following code to scan the input from my files test1.txt and test2.txt using SAS University edition. I have also placed it in the question using the SAS icon.
%macro datm1;
%do i=1% to 2;
data NEW&i;
libname OLD "/folders/myfolders/bootprocess/";
/*Input D*/
datafile="/folders/myfolders/bootprocess/TEST&i..DAT/";
INPUT @ 1 CHECK $CHAR200.@;
/*DATA NAME IS CHECK WHICH IS INDEXED W/'THETA =' THIS MUST BE EXACT*/
S=INDEX(CHECK,'THETA =');
/*DO LOOP TO PICK OUT CORRECT LINE OF CODE LINE W/STRING WILL BE NUMBERED WITH 1 OTHERS=0*/
/*SCAN FUNCTION ALLOWS VARIABLES TO BE OUTPUT FROM THAT POSITION WITH THE DESIRED NAME*/
IF S>0 THEN DO;
THETA_=SUBSTR(CHECK,S+0,110);
K13=SCAN(THETA_,1,' ');
K23=SCAN(THETA_,2,' ');
DURATION=SCAN(THETA_,3,' ');
LAG=SCAN(THETA_,4,' ');
LOGIT=SCAN(THETA_,5,' ');
K30 =SCAN(THETA_,6,' ');
K34= SCAN(THETA_,7,' ');
VOLUME=SCAN(THETA_,8,' ');
OUTPUT;
END;
PUT K13 K23 DURATION LAG LOGIT K30 K34 VOLUME;
KEEP K13 K23 DURATION LAG LOGIT K30 K34 VOLUME;
*PROC PRINT;
RUN;
dATA PEW;
SET NEW;
PROC PRINT;
RUN;
When I run the code I get no output but an error 49 which states " The meaning of an identifier after a quoted string might change in a future SAS release. Inserting white space between a quoted string and the succeeding identifier is recommended." I really habe no idea what this means. Can anyone tell me what is the problem and how I can solve it? The data sets test1 and test 2 are the same.
@jacksonan123 wrote:
The current macro that I have runs just fine with the libname and when it is
removed I get an error.
The libname is being used by SASuniversity for the infile statement.
Unless the INFILE statement looks like this
infile "%sysfunc(pathname(OLD))/TEST&i..smr" truncover;
then the INFILE statement is in no way using the libname statement for anything.
Now your code or your SAS/Studio session might be using the libref OLD for something. But since its definition does NOT depend on the macro variables used in the macro there is no reason why it cannot be defined outside of the macro.
libname OLD "/folders/myfolders/bootprocess/";
%datm1;
Or if it is defined in the macro then define it outside of the %DO loop instead of defining it twice.
%macro datm1;
libname OLD "/folders/myfolders/bootprocess/";
%do i=1% to 2;
...
%end;
%mend datm1;
You need to show us more! You create a macro, but don't show how it ends (i.e., a %mend; statement), you start a %do loop (the % to may or may not work .. should be %to), but I didn't see a %end statement, you create new1 and new2, but then try to print new, and you use a datafile statement (which I've never seen before) where you probably want to use an infile statement, your libname and datafile statements end with / which might be ok for the libname (but not needed), but I don't think will work with the infile statement, and, finally, you never show us an example dataset or show us the statement that calls the macro.
Art, CEO, AnalystFinder.com
The following corrects for the errors I mentioned in my first post, as well as a couple of additional problems. NEVER use the * type comment in a macro!
I'm not sure what you are trying to do, but try and then examine the results of the following code:
%macro datm1; /* %do i=1% to 2;*/ %do i=1 %to 2; data NEW&i; libname OLD "/folders/myfolders/bootprocess/"; /*Input D*/ /* datafile="/folders/myfolders/bootprocess/TEST&i..smr/";*/ infile "/folders/myfolders/bootprocess/TEST&i..smr" truncover; /* INPUT @ 1 CHECK $CHAR200.@;*/ INPUT @ 1 CHECK $CHAR200.; /*DATA NAME IS CHECK WHICH IS INDEXED W/'THETA =' THIS MUST BE EXACT*/ S=INDEX(CHECK,'THETA ='); /*DO LOOP TO PICK OUT CORRECT LINE OF CODE LINE W/STRING WILL BE NUMBERED WITH 1 OTHERS=0*/ /*SCAN FUNCTION ALLOWS VARIABLES TO BE OUTPUT FROM THAT POSITION WITH THE DESIRED NAME*/ IF S>0 THEN DO; THETA_=SUBSTR(CHECK,S+0,110); K13=SCAN(THETA_,1,' '); K23=SCAN(THETA_,2,' '); DURATION=SCAN(THETA_,3,' '); LAG=SCAN(THETA_,4,' '); LOGIT=SCAN(THETA_,5,' '); K30 =SCAN(THETA_,6,' '); K34= SCAN(THETA_,7,' '); VOLUME=SCAN(THETA_,8,' '); OUTPUT; END; PUT K13 K23 DURATION LAG LOGIT K30 K34 VOLUME; KEEP K13 K23 DURATION LAG LOGIT K30 K34 VOLUME; /* *PROC PRINT;*/ RUN; /* dATA PEW;*/ /* SET NEW;*/ PROC PRINT; RUN; TITLE ' DISTRIBUTION DATA'; /* data distrR;*/ /* set %do i=1% to 2;new&i %end ;;*/ proc append base=master data=new&i; /**PROC PRINT;*/ RUN; %end; /*%mend datm;*/ %mend datm1; %datm1; /*run;*/
Art, CEO, AnalystFinder.com
I commented those lines out because: (1) you were setting the macro variable i in two overlapping loops and it didn't make any sense (to me) to be using an append statement to create two master files that each would only include the files you already created.
You would have to post the code you actually ran but, before doing so, change the second loop to something other than I (e.g., J)
And, if you want to solve it yourself, first run:
options mprint mlogic symbolgen;
That way you will be able to see what is going on in the background throughout the code.
Art, CEO, AnalystFinder.com
Makes perfect sense .. but the logic of your code doesn't!.
Think about it! You have a major loop where you are creating NEW1 and NEW2. However, in the middle of that loop you are trying to create three copies of the same thing, one called distrR and the other called master1 and master2.
Since the I loop doesn't %end until the end of the program, the first time through it can't create distrR the way you want because only one of the files had been created at that point. The loop doesn't end until I gt 2 (i.e., 3), thus that is its value by the time it gets to the proc append statement.
You'll have to tell us what you really want to create in those two segments (i.e., distrR and master&i) in order for anyone to give you good advice.
Art, CEO, AnalystFinder.com
I would suggest taking a step back and getting the data step working for a single file first. Later you can back the macro %DO loop if you need it. It is much easier to debug without having to use macro code.
Also post an example input file and we can help you simplify the data step. If the data is really space delimited then why not just use the INPUT statement to read it rather than reading it into a character varaible and then having to parse it. Plust that way it will be easier to read the numeric fields into numeric variables.
Something like this might work.
data new1 ;
infile "/folders/myfolders/bootprocess/TEST1.DAT";
input @;
if index(_infile_ , 'THETA =') then do;
input @'THETA =' +110 THETA K13 K23 DURATION LAG LOGIT K30 K34 VOLUME;
output;
end;
run;
data _null_;
set new1 ;
put (_all_) (=/);
run;
Why did you still post the start of data step with a LIBNAME statement embedded into the middle of it?
The LIBNAME statement will have NOTHING to do with the data step. It will be compiled before the data step starts. Plus you code isn't even referencing the libref it creates.
@jacksonan123 wrote:
The current macro that I have runs just fine with the libname and when it is
removed I get an error.
The libname is being used by SASuniversity for the infile statement.
Unless the INFILE statement looks like this
infile "%sysfunc(pathname(OLD))/TEST&i..smr" truncover;
then the INFILE statement is in no way using the libname statement for anything.
Now your code or your SAS/Studio session might be using the libref OLD for something. But since its definition does NOT depend on the macro variables used in the macro there is no reason why it cannot be defined outside of the macro.
libname OLD "/folders/myfolders/bootprocess/";
%datm1;
Or if it is defined in the macro then define it outside of the %DO loop instead of defining it twice.
%macro datm1;
libname OLD "/folders/myfolders/bootprocess/";
%do i=1% to 2;
...
%end;
%mend datm1;
Looking at your raw data, I will guess that you really want to read some of the other fields in your data. However, the following matches most of the calculations described in the data. This time, I chose to read them directly rather than scanning a text field:
%macro datm1; %do i=1 %to 2; data NEW&i; /*Input D*/ infile "/folders/myfolders/bootprocess/TEST&i..smr"; INPUT @ 'THETA =' K13 K23 CL V3 D1 TLAG2 LOGITT; ALAG2=sum(D1,TLAG2); TVF1=1/(1+EXP(-LOGITT)); F1=TVF1; S3=V3/1000; F2=1-F1; K30=CL/V3; run; %end; TITLE ' DISTRIBUTION DATA'; data distrR; set %do i=1 %to 2;new&i %end ;; run; %mend datm1; %datm1;
Art, CEO, AnalystFinder.com
Code works well.
Thanks
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
What’s the difference between SAS Enterprise Guide and SAS Studio? How are they similar? Just ask SAS’ Danny Modlin.
Find more tutorials on the SAS Users YouTube channel.