_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');这一句能够正常执行。其原因在于:
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
| %let dsid=%sysfunc(open(sashelp.class,i)); %syscall set(dsid); %let rc=%sysfunc(fetchobs(&dsid,10)); %put _user_; %let rc=%sysfunc(close(&dsid)); |

(楼 2 of 2)
Scopeof Macro Variable
SAS中的宏变量可以分为Global和Local两类。分别存放于Global Symbol Table和Local Symbol Table。
Global Symbol Table只有一个,在SAS进程开始时被创建,在进程结束时删除。
Local Symbol Table在宏开始执行时创建,宏执行完毕后删除,每一个宏在执行时都会有各自的Local Symbol Table。
Global的宏变量自被创建起,直至被删除或当前SAS进程结束,都会存在;并且可以在open code或宏的内部使用。而local的宏变量只是在宏执行过程中存在,只能在宏的内部使用。
_AUOMATIC_宏变量
SAS启动时所创建的_automatic_宏变量中,除了SYSPBUFF之外,都是Global的。SYSPBUFF的情况比较特殊,通过下面的例子我们可以总结SYSPBUFF的特点如下:
· 在open code中运行%put _automatic_; 可以看出SYSPBUFF属于_automatic_;
· SYSPBUFF只有在宏运行的时候才会存在,因此不能在open code中输出或改变它的值。而在宏定义中,通过下面的方式都可以使SYSPBUFF存在或改变它的值:
* 使用%LET语句更新SYSPBUFF的值,%LET语句之后执行%put _automatic_;会发现SYSPBUFF的值已经改变。
* 使用%local syspbuff;(这种用法是不正常的,在这里仅仅是为了测试SYSPBUFF的scope)。
* 使用/parmbuff,这种是使用SYSPBUFF的常规方法,而且会在宏开始执行时便为SYSPBUFF赋值。
· 通过使用%SYMGLOBL和%SYMLOCAL可以判断:
* 在open code中SYSPBUFF在Global Symbol Table中不存在。
* 在宏执行过程中,SYSPBUFF总是存在于Global Symbol Table,而不是Local Symbol Table中,即便是使用了%local syspbuff;。
%put _automatic_; %put &syspbuff; %let syspbuff=aaa; %put Is SYSPBUFF Global?: %symglobl(syspbuff); %macro test; %put ---SYSPBUFF: &syspbuff; %let syspbuff=aaaaa; %put _automatic_; %put ---SYSPBUFF: &syspbuff; %put ; %put ---Is SYSPBUFF Global?: %symglobl(syspbuff); %put ---Is SYSPBUFF Local?: %symlocal(syspbuff); %mend; %test %macro test1; %local a b c syspbuff ; %put ---SYSPBUFF: &syspbuff; %put ; %put ---Is SYSPBUFF Global?: %symglobl(syspbuff); %put ---Is SYSPBUFF Local?: %symlocal(syspbuff); %mend; %test1 %macro test2(var)/parmbuff; %put ---SYSPBUFF: &syspbuff; %put ; %let syspbuff=hahaha; %put ---SYSPBUFF: &syspbuff; %put ; %put ---Is SYSPBUFF Global?: %symglobl(syspbuff); %put ---Is SYSPBUFF Local?: %symlocal(syspbuff); %mend; %test2(abcde,dsn=class) |
如果宏变量已经存在
当SAS为一个宏变量赋值时,SAS会从里到外(即从最内层的Local Symbol Table一直到Global Symbol Table)查找该宏变量是否已经存在。如果SAS在某个位置找到了这个宏变量,就会执行赋值操作,查找的动作也随即停止。比如:
| %symdel i tmp/ nowarn; %let i=1; %let tmp=value from open code.; %macro inner(i_value); %let tmp=value from inner; %let i=&i_value; %put _local_; %mend; %macro outer; %local tmp; %let tmp=value from outer; %let i=2; data test; v=3; call symputx("i",v); run; proc sql noprint; select distinct "4" into :i from test; quit; %do i=5 %to 100; %end; %inner(1000) %put _local_; %mend; %outer %put Now value of macro variable i is: &i; %put Now value of macro variable tmp is:&tmp; |
上面的例子中:
· 对于宏变量i,无论是CALL SYMPUTX(), PROC SQL, 还是%LET 或%DO语句,当它们试图为宏变量i赋值时,所改变的总是Global Symbol Table中的宏变量i的值。宏outer和inner在执行时都没有在自己的Local Symbol Table中创建宏变量 i 。
· 对于宏变量tmp,由于宏outer中有local的宏变量tmp,所以inner执行时改变的是宏outer中的tmp的值,而不能改变Global Symbol Table 中tmp的值。
如果宏变量不存在
当SAS对宏变量赋值时,如果宏变量不存在:
1. %LET语句会在当前位置创建宏变量。如果是在open code中,则创建global的宏变量,如果是在宏中,则会为%LET语句所在的宏创建local的宏变量。
2. %DO语句会在所在的宏创建local宏变量。
3.宏中的PROCSQL INTO语句会创建local的宏变量。
4.宏中的参数会作为宏的local宏变量。
5. CALL SYMPUT () 会在离它所在的DATA步最近的,并且非空的symbol table创建宏变量。也就是,如果DATA步执行时Local Symbol Table 中已经有宏变量,则CALLSYMPUT () 会将宏变量创建在LocalSymbol Table中。否则就会向外层查找,直到Global Symbol Table. 下面的特殊情况可以使CALLSYMPUT () 创建local的宏变量:
| %symdel var /nowarn; %macro test; %let syspbuff=bbbb; data _null_; call symput("var","&syspbuff"); run; %put _local_; %put ---Is VAR Global?: %symglobl(var); %put ---Is VAR Local?: %symlocal(var); %mend; %test |
| %symdel var/nowarn; %macro test; %put _local_; data _null_; call symput("var","bbbbb"); run; %put _local_; %let home=last; %goto &home; %last: %mend; %test |
| %symdel var/nowarn; proc sql; quit; %macro test; proc sql; create table class as select distinct * from sashelp.class; quit; data _null_; call symput("var","aaaa"); run; %put _local_; %put ---Is VAR Global?: %symglobl(var); %put ---Is VAR Local?: %symlocal(var); %mend; %test %symdel var sqlobs/nowarn; %test |
扫码加好友,拉您进群



收藏
