SAS:从另一个宏调用一个宏...宏定义的顺序

时间:2009-02-11 15:18:37

标签: sas sas-macro

在我的代码中,我有几个宏。宏A是主宏。宏A然后调用宏B,宏B又调用宏C.

在SAS中,我是否必须按向后顺序定义它们?换句话说,我必须首先定义宏C,然后定义宏B,然后定义宏A吗?或者它是否重要,因为SAS在实际命中运行宏之前读取所有代码?就此而言,我可以发出命令将宏作为代码中的第一个语句运行,然后在命令下面定义宏吗?

谢谢!

4 个答案:

答案 0 :(得分:3)

首先,您必须在调用宏之前定义它。

其次,只要您在事先加载宏,调用宏的位置并不重要。

详细说明您的问题:自动调用库是您的朋友。如果您的SAS管理员不允许您将宏放入自动调用库中,则可以像这样附加自动调用:

filename mymacros 'c:\mysas'; 
/*this defines the directory you have stored your macros*/

options sasautos=(sasautos mymacros) mautosource; 

答案 1 :(得分:3)

在调用宏之前必须定义一个宏。出于性能原因,最好不要在另一个宏中定义宏 - 如果这样做,那么每次调用外部宏时都会重新定义它。以下工作正常:

%macro a;
  %put a;
  %b
%mend a;

%macro b;
  %put b;
  %c
%mend b;

%macro c;
  %put c;
%mend c;

%*-- %a is main --*;
%a
/* on log
a
b
c
*/

答案 2 :(得分:1)

您必须在调用宏之前定义宏,因此带有“%A”的行需要遵循宏A的定义。其他宏定义的顺序无关紧要,只要它们在它们之前定义叫做。通常在我的程序中,我设置了一个像你描述的主宏,然后程序的最后一行调用这个宏。

要考虑的另一个选择是设置宏自动调用库,其中包含许多宏的定义。这最适用于可重用的宏,因此您不必在每个程序中重新定义它们。

答案 3 :(得分:0)

要定义SAS中的宏代码有两个方面:编译的宏代码和宏参数:

宏代码:

宏代码本身非常简单,因为当遇到%macro令牌时,SAS系统开始编译SAS宏并继续编译,直到它到达%mend令牌。您可以遇到的唯一真正问题是,如果您更新宏代码并且在执行之前不重新编译它 - 在这些情况下它仍将运行它在宏库中的旧版本。通过扩展,如果您尝试编译一个调用另一个尚未定义的宏的宏,那么您将收到错误。由于这些原因,它们需要按照调用它们的顺序进行编程(如下例所示:%level3出现在%level2之前,它出现在%level1之前)

宏变量: 定义宏变量时,有两个范围:全局和本地。定义后,可以随时随地访问全局变量。但是,局部变量仅在执行已定义的宏期间本地存在。通过扩展,如果已定义局部变量的宏调用任何其他宏,则仍可访问本地宏变量:

工作示例:

在以下示例中,宏以相反顺序定义,以防止SAS返回明显调用宏警告。

下图说明了以下示例中以下宏的结构:

|-----------------------------|
|GLOBAL                       |
|  |------------------------| |
|  |LEVEL1                  | |
|  |  |-------------------| | |
|  |  |LEVEL2             | | |
|  |  |  |--------------| | | |
|  |  |  |  LEVEL3      | | | |
|  |  |  |--------------| | | |
|  |  |-------------------| | |
|  |------------------------| |
|-----------------------------|

编译嵌套宏:

 %macro level3 ;
  %put **** START LEVEL3 **** ;
  %local G1;
  %let G1=Local ;

  %do i=1 %to 2 ;
    %put In the macro do loop I=&i ;
  %end ;

  %put The value of I at level3 is: &I ;
  %put Are we accessing global or local G1 variable here: &G1 ;

  %put **** END LEVEL3 ****;
%mend level3 ;


 %macro level2 ;
  %put **** START LEVEL2 **** ;
  %*global L1 ; *<-- this would produce an error because the variable name has already been added to the local scope in %level1 ;

  %put Are we accessing global or local G1 variable here: &G1 ;
  %put Can we access local variables here: &L1 ;

  %level3 ;

  %put The value of I in level2 is: &I ;
  %put **** END LEVEL2 ****;
%mend level2 ;

编译顶级宏(进而调用上面两个宏)并运行它:

%let G1=Global;
%macro level1 ;
  %put **** START LEVEL1 **** ;
  %let L1=Yes;

  %put Are we accessing global or local G1 variable here: &G1 ;
  %put Can we access local variables here: &L1 ;

  %level2 ;

  %put The value of I outside of the local macro is: &I ;
  %put Are we accessing global or local G1 variable here: &G1 ;

  %put **** END LEVEL1 ****;
%mend level1 ;
%level1 ;

查看日志时需要注意的事项:

  • 在%level3之外,&amp; I返回宏变量的警告 不存在
  • 在%level3内,当调用&amp; G1时,它返回存储的值 %level3的局部范围。在%level3之外,值返回 到全球存储的值