Creation of Macro Variable
在SAS中,宏变量可以在data lines之外的任何地方使用,一般来说宏变量的产生有以下情况:
_AUOMATIC_
SAS启动时,会自动产生一些宏变量。如SYSDATE、SYSDAY、SYSTIME、SYSUSERID、SYSVER、SYSMACRONAME等等。可以通过运行%put _automatic_;查看。
_automatic_ macro variable中,有些值是固定的,如SYSDATE和SYSTIME的值分别是SAS启动时的日期和时间;有些值是可以变化的,比如SYSLAST保存的是最后被创建的数据集的名字。
%LET variable=value;
%LET语句是定义宏变量最为直观的方法。如果%LET语句指定的宏变量不存在,则SAS会创建该宏变量;如果该宏变量已经存在,那SAS会更新宏变量的值。
用%LET对宏变量赋值时不需要用引号,如果使用了引号,引号会作为值的一部分。
%LET赋值时,等号右边的值没有所谓的数据类型之分,而是都会被作为字符处理,不会进行运算。例如 %let x=1+1;,宏变量x的值是1+1,而不是2。(可以通过运用宏函数,如%EVAL()等,来进行运算)
CALLSYMPUT () / CALL SYMPUTX ()
CALLSYMPUT () 和CALL SYMPUTX ()可以实现在DATA步的执行过程中创建宏变量。二者的主要区别在于CALL SYMPUTX ()会将第二个参数值前面和后面的空格去掉;并且CALL SYMPUTX ()有第三个参数来限定宏变量存放的位置。
关于CALL SYMPUT ()有一条几乎人尽皆知的规则是:不可以在同一个DATA步中“引用”CALL SYMPUTX ()创建的宏变量,但可以在同一个DATA步中“使用”。比如:
%symdel userid/nowarn;
data test; call symputx("userid","&sysuserid"); userid1="&userid"; userid2=symget("userid"); put userid1= ; put userid2= ; run; |
上面的例子中userid1="&userid";这一句会产生一条WARNING,而userid2=symget('userid');这一句能够正常执行。其原因在于:
- CALL SYMPUTX ()创建宏变量是在DATA步的执行阶段;
- userid1="&userid";这句要求在DATA步的编译阶段就得到userid的值,而此时该宏变量还未被创建;
- SYMGET() 是在DATA步执行阶段运行到该句时才去找宏变量的值,其参数只是宏变量的名字,而不需要&符号。
PROC SQL
PROC SQL的INTO子句可以将变量的值存到宏变量中:
select avg(weight) into :mvar from sashelp.class; § 会计算sashelp.class中各条记录的平均体重,并存入宏变量mvar中。 select name into :mvar1 -:mvar99 from sashelp.class § 这一句会将变量name的值依次存入宏变量mvar1,mvar2,… § 由于sashelp.class只有19条记录,这一句也就只会创建mvar1 - mvar19这19个宏变量。 § 如果from子句后跟上order by name desc;,那么的mvar1值就会是倒序排列的第一个name值William,而mvar19的值将会是Alfred。 select name into :nmlist separated by ", " from sashelp.class § 这句会将变量name的各个值用", "来分隔,并存入到宏变量nmlist中。同样,where和order by分别会改变name的个数和顺序。 |
SAS在执行完每一个PROC SQL步之后,都会产生或更新某些宏变量如SQLOBS、SQLOOPS、SQLRC等,比较常用的是SQLOBS,这个宏变量的值可以是SQL选出的或删除的观测数。例如:
proc sql noprint; *** Number of rows selectd; create table boys as select * from sashelp.class where sex="M";
%put ----Number ofboys in sashelp.class: &sqlobs;
*** Number of rowed deleted; delete from boys where name eqt "J";
%put ----Number ofboys whose name starts with "J": &sqlobs;
*** Number of rows involved in creating macro variablelist; select Name into :name1-:name999 from sashelp.class where age=12;
%put ----Number ofstudents who is 12 years old: &sqlobs. ; quit; |
SYSPBUFF
SYSPBUFF是一个_AUTOMATIC_ macro variable。但这个宏变量不能在open code里使用,只能在宏里面使用,通常情况下是要在定义宏程序的时候使用PARMBUFF选项。在宏内使用这个宏变量时,SYSPBUFF记录的是在调用宏的时候所提供的参数的值,包括从左括号到右括号的所有字符在内。通过使用PARMBUFF,可以实现在调用宏的时候参数的个数和参数值更加灵活,而且并不影响正常的参数值的传递。
这里需要注意的是:通常在调用宏时,后面不需要加一个“多余的”分号,然而如果定义宏时使用了PARMBUFF,那在调用时SAS会“等待”后面将要赋给SYSPBUFF的值。因此,在调用一个没有参数的宏(类似%macro a/parmbuff;),并且不需要传给SYSPBUFF任何值的时候,需要在宏名字后加一个分号来表示调用的结束%a;。
具体可以看下面的例子:
*** Without parameters; %macro a/parmbuff; %put --Value of SYSPBUFF:&syspbuff; %mend;
%a; %a() %a(haha) %a(one=1,two,three is 3)
*** With name-style parameters; %macro b(ds,var)/parmbuff; %put --Value of SYSPBUFF: &syspbuff; %put --Value of Parameters: &ds &var; %mend;
%b(a,b) %b(d,e,f,g)
*** With keyword-style parameter; %macro c(var=)/parmbuff; %put --Value of SYSPBUFF:&syspbuff; %put --Value of Parameters: &var; %mend; %c(var=adsdsas) %c(,,whatever you want vars=sa) |
Other
- Macro Parameters
如果定义宏时使用了参数,那在宏执行的过程中,参数都会作为宏变量存在。 - %do i=1 %to 5; ... %end;
%do语句中的指示变量 i 也是宏变量。 - 下面的语句会对sashelp.class中的每个变量都创建相同名字的宏变量,并保存该变量在第十行记录的值。
%let dsid=%sysfunc(open(sashelp.class,i)); %syscall set(dsid); %let rc=%sysfunc(fetchobs(&dsid,10)); %put _user_; %let rc=%sysfunc(close(&dsid)); |