2月 14, 2011

Posted by in | 1 条评论

SAS macro symbol table(2):特殊规则

上篇对macro symbol table的常规应用进行了简单的梳理,本篇对如call symput的非宏语言在建立宏变量时symbol table的特殊规则进行梳理。

1.the into : operator in PROC SQL

“into :”算符并不不属于宏语言,但是其定义宏变量的过程基本与使用%let相同:先由当前local,再向上级直到global中搜寻所定义的宏变量是否存在,再进行相应的处里。参见SAS macro symbol table(1)

style=”text-align: center;”>需要了解的是,在proc sql执行过程中,会自动产生三个包含该proc sql过程信息的宏变量:sqlobs、sqlrc和sqloops,如下:

  • SQLOBS: set to the number of rows produced with a SELECT statement.
  • SQLRC: set to the return code from an SQL statement.
  • SQLOOPS: set to the number of iterations of the inner loop of PROC SQL.

合理的使用以上三个宏变量,对程序的编写可以起到很好的作用。

2.call symput DATA step routine

2.1常规情况

由于call symput并不是属于宏语言,所以其定义宏变量的过程与%let等并不相同,具体规则为:当data步执行时,如果当前的symbol table不为空,call symput 在当前的symbol table中建立宏变量;如果当前symbol table完全为空,则call symput向上搜寻直到global,在最近的非空symbol table中建立宏变量。

注意上述“当前symbol table完全为空”:

  • 此主要对于local symbol table而言,因为global symbol table始终不为空(即在open code中,call symput直接建立全局宏变量)。
  • 只要当前local不为空即可,不需要管所定义的宏变量是否已存在。我们知道,对一个非空local,使用%let定义宏变量A时,若宏变量A不存在,向上级直到global中搜寻再处理;而使用call symput时,直接在当前local中建立宏变量A。

具体参见以下例子:

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
/*Example 1:CALL SYMPUT with Complete DATA Step and Nonempty Local*/
%macro test1(local_p);
	data _null_;
		x1='it is test1';
		call symput('m_var1',x1);
	run;
	%put ** Inside the macro: **;
	%put _user_;
%mend;
%test1(1)
data temp1;
	y1="&m_var1";
run;
%put ** In open code: **;
%put _user_;
 
/*Example 2:CALL SYMPUT with Complete DATA Step and empty Local*/
%macro test2;
	data _null_;
		x2='it is test2';
		call symput('m_var2',x2);
	run;
	%put ** Inside the macro: **;
	%put _user_;
%mend;
%test2
data temp2;
	y2="&m_var2";
run;
%put ** In open code: **;
%put _user_;
  • Example 1,log显示如下。宏test1的local不为空,所以直接在其中建立局部宏变量m_var1,在宏test1执行完后local symbol table被清空,所以外部的data temp1中的&m_var1无法解析,输出警告。
** Inside the macro: **
TEST1 LOCAL_P 1
TEST1 M_VAR1 it is test
WARNING: Apparent symbolic reference M_VAR1 not resolved.
  • Example 2,log显示如下。宏test2的local完全为空,所以向上到global中建立宏变量m_var2,并且外部的data temp2中的&m_var2解析为“it is test2”。
** Inside the macro: **
GLOBAL M_VAR2 it is test2
NOTE: The data set WORK.TEMP2 has 1 observations and 1 variables.
** In open code: **
GLOBAL M_VAR2 it is test2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*Example 3:CALL SYMPUT with Incomplete DATA Step and Nonempty Local*/
%macro test3(local_p);
	data _null_;
		x3='it is test3';
		call symput('m_var3',x3);
	%put ** Inside the macro: **;
	%put _user_;
%mend;
%test3(3)
run;
data temp3;
	y3="&m_var3";
run;
%put ** In open code: **;
%put _user_;
  • Example 3,log显示如下。注意,与Example 1相比,宏test3中的data是不完整的(缺少“run”),直到遇到open code中的“run”,所以当前的symbol table是global,所以m_var3建立在global,并且外部的data temp3中的&m_var3解析为“it is test3”。
NOTE: The data set WORK.TEMP3 has 1 observations and 1 variables.
** In open code: **
GLOBAL M_VAR3 it is test3
2.2特殊情况
  • 若call symput在proc sql之后使用,宏变量一定建立在local中。因为proc sql会自动产生局部宏变量如sqlobs等,所以local非空。
  • 宏调用时建立宏变量syspubff,其在local中。

SYSPBUFF: contains text supplied as macro parameter values. Used in conjunction with macro programs defined with the PARMBUFF option.

  • 执行的宏包含一个computed %goto语句时,宏变量建立在local在中。

%GOTO label: ranches macro processing to the specified macro label within the macro program.

具体参见以下例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*Example 4:CALL SYMPUT with SYSPBUFF and empty Local*/
%macro test4 / parmbuff;
	data _null_;
		x4='it is test4';
		call symput('m_var4',x4);
	run;
	%put ** Inside the macro: **;
	%put _user_;
	%put &syspbuff;
%mend;
%test4
data temp4;
	y4="&m_var4";
run;
%put ** In open code: **;
%put _user_;
%put &syspbuff;
  • Example 4,log显示如下。因为宏变量syspbuff包含所有宏的所有参数值列表,所以在宏调用时建立syspbuff,即使当前local为空,call symput也“认为”其不空,进行处理,建立局部(local)宏变量。
** Inside the macro: **
TEST4 M_VAR4 it is test4

	y4="&m_var4";
WARNING: Apparent symbolic reference M_VAR4 not resolved.

** In open code: **
WARNING: Apparent symbolic reference SYSPBUFF not resolved.
&syspbuff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*Example 5:CALL SYMPUT with %GOTO and empty Local*/
%macro test5;
	%goto &want;
		%height:
		data temp_h(keep=name height);
			set sashelp.class;
			call symput('m_var5',height);
		run;
		%weight:
		data temp_w(keep=name weight);
			set sashelp.class;
			call symput('m_varm5',weight);
		run;
	%put ** Inside the macro: **;
	%put _user_;
%mend;
%let want=weight;
%test5
data temp5;
	y5="&m_var5";
run;
%put ** In open code: **;
%put _user_;
  • Example 5,log显示如下。因为%goto语句会转到定义好的宏标签,而其并不知道宏标签的symbol table情况,所以,即使当前的local为空,call symput也“认为”其不空,进行处理,建立局部(local)宏变量。
** Inside the macro: **
TEST5 M_VARM5          112
GLOBAL WANT weight

	y5="&m_var5";
WARNING: Apparent symbolic reference M_VAR5 not resolved.

** In open code: **
GLOBAL WANT weight

3.call symputx DATA step routine

call symputx用法基本与call symput相同,但call symputx多了一个参数可以直接指定宏变量的symbol table,如下:

CALL SYMPUTX(macro-variable, text<,symbol-table>)

The third argument is optional and it tells the macro processor the symbol table where the macro variable should be stored, and it can be one of three values:

  • G, 定义宏变量在global中,即使local存在。
  • L, 定义宏变量在最内层的local中。当该宏程序未执行时,不存在local,此时最内层的就是global了,宏变量存储于其中。
  • F, 定义宏变量可以在任何symbol table中。CALL SYMPUTX 会更新包含该变量的最内层的local,所有的local都不存在是,在最内层local建立存储该宏变量。

尤其需注意使用“L”和“F”的区别。

4.other tips

  • 可以在sashelp.vmacro中查看所有存在的宏变量的scope和value等信息。
  • 可以通过使用%symdel来删除全局(global)宏变量,不可删除局部(local)宏变量。

例:Delete all user-defined macro variables from the global symbol table

  • 可以通过%symexist、%symglobal、%symlocal 来检验宏变量、全局宏变量、局部宏变量是否存在。

 

参考文献
1.SAS 9.2 Macro Language Reference
2.Carpenter’s Complete Guide to the SAS Macro Language (2nd Edition)

  1. 虽不太懂SAS~但继续顶一个

    [回复]

发表评论

返回顶部