Macro Variables¶
Generally, the final component of a program header are the program-specific macro variables. SAS macro variables allow you to modify the text in a SAS program through symbolic substitution (think local
and global
from Stata). SAS macro variables are declared by a %LET
statement followed by the macro name, an equals sign, and finally the value to be stored in the macro. You can store anything in a SAS macro.
%let fcohort = 1978;
%let lcohort = 1991;
%let file_name = example.txt;
To refer to a previously declared SAS macro variable, you type the macro name (i.e. fcohort) contained by &
and .
. For example, to keep rows of data for kids born between 1978-1991 using the macro variables above, we would write:
if cohort >= &fcohort. and cohort <= &lcohort.;
A note on the use of &
and .
with Macros and Nested Macros¶
Here we discuss macro processing in more detail, you should skip this portion for now and come back when useful. In general, there is no need to include the .
delimiter at the end of the macro name when envoking a SAS macro variable - the &
will suffice. For example, the sample code above will work without the periods:
if cohort >= &fcohort and cohort <= &lcohort;
There are times, however, when the .
is required to delimit the end of a macro variable, so it is good practice to include them. For example, when using macro variables nested within text or code, the .
is needed to signify the end of the macro variable. This is illustrated below:
First we define our macro suffix
%let suffix = ing;
The safe way to invoke this macro is
* This is the safe way;
%PUT swimm&suffix.;
which would output
57 * This is the safe way;
58 %PUT swimm&suffix.;
swimming
However, in this case we can omit the .
and get the same result
* This gives the same result;
%PUT swimm&suffix;
which gives
60 * This gives the same result;
61 %PUT swimm&suffix;
swimming
If there were characters following the macro that are not part of the macro then omitting the .
character would cause an error as below where SAS looks for the macro named suffixly
* This will not work, SAS looks for macro "suffixly";
%PUT swimm&suffixly;
63 * This will not work, SAS looks for macro "suffixly";
WARNING: Apparent symbolic reference SUFFIXLY not resolved.
64 %PUT swimm&suffixly;
swimm&suffixly
Adding the .
to denote the end of the macro fixes this
* This works, SAS knows macro is suffix;
%PUT swimm&suffix.ly;
66 * This works, SAS knows macro is suffix;
67 %PUT swimm&suffix.ly;
swimmingly
You can see how SAS interprets the different macro variables we defined in the code above. The %PUT
statement acts like a print statement here and the output can be seen under lines 61, 64, and 67.
Nested Macros¶
We can also nest macro variables inside of each other, although things become a bit more complicated here. If you want to understand how SAS will resolve these macros you need to understand the rules of SAS macro variables
Never talk about SAS macro variables
Two ampersands always resolve to one ampersand.
The macro parser always continues reading left to right until the end of the reference is reached.
If a reference contains consecutive ampersands, after resolution at least one more read will follow.
To illustrate these rules lets consider a few examples. First lets define some macro variables
%let year = 99;
%let century = 19;
%let cpi1999 = 1.05;
Think about how the macro parser will treat
%PUT &cpi¢ury&year;
First it will try to resolve &cpi
, however this doesn’t exist so it will leave it as is. Then it will resolve ¢ury
to 19
and &year
to 99
which results in &cpi1999
since there were no consecutive ampersands the macro processor terminates.
WARNING: Apparent symbolic reference CPI not resolved.
74 %PUT &cpi¢ury&year;
&cpi1999
What if we use two ampersands in the beginning
%PUT &&cpi¢ury&year;
First the macro parser resolves &&
to &
then it tries to resolve ¢ury
followed by &year
resulting in &cpi1999
. Since we had consecutive ampersands the macro parser does one more read and resolves &cpi1999
to 1.05
90 %PUT &&cpi¢ury&year;
1.05
Now let’s try something a little more complicated
%let pre = cpi
%let suf = year
%let cpiyear = 1999
%let cpi1999 = 1.07
Let’s try to invoke cpi1999
using pre
, suf
, and cpiyear
. Let’s start from the final line we want
%PUT &cpi1999;
Now we want &cpiyear
to resolve to 1999
and we want a singular ampersand in the front. So we sub &cpiyear
for 1999
and &&
for &
(because two ampersands resolve to one)
%PUT &&cpi&cpiyear;
Now we need to sub in &pre
for cpi
and &suf
for year
%PUT &&cpi&&pre&suf;
However, this will not work and will resolve to &cpi&preyear
. This is because we forgot to deal with &&
and &
. To retain &&
we should use &&&&
and to retain &
we should use &&
which gives
%PUT &&&&cpi&&&pre&suf;
which gives
54 %PUT &&&&cpi&&&pre&suf;
1.07
55
Let’s step through this. In the first pass, the macro parser first resolves &&&&cpi
to &&cpi
, then &&
to &
, then &pre
to cpi
, then &suf
to year
giving &&cpi&cpiyear
. On the second pass, it resolves &&cpi
to &cpi
and &cpiyear
to 1999
giving &cpi1999
. Finally, since there was a double ampersand, the macro parser does one final pass and resolves &cpi1999
to 1.07
.
This example was needlessly complicated to illustrate some of the macro parser rules. You will rarely have to use something this complicated but it may come in handy at some point.