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

SAS:从一个宏调用另一个宏…宏定义的顺序,sas,sas-macro,Sas,Sas Macro,在我的代码中有几个宏。宏A是主宏。然后宏A调用宏B,宏B又调用宏C 在SAS中,是否必须按向后顺序定义它们?换句话说,我必须先定义宏C,然后定义宏B,最后定义宏A吗?还是因为SAS在实际执行运行宏的命令之前读取了所有代码,所以这很重要?就此而言,我是否可以发出命令,将宏作为代码中的第一条语句运行,然后在命令下面定义宏 谢谢 您必须在调用宏之前定义它,因此带有“%a”的行需要遵循宏a的定义。其他宏定义的顺序无关紧要,只要在调用之前定义它们即可。通常,在我的程序中,我设置了一个如您所述的主宏,然后程

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

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


谢谢

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


另一个要考虑的选项是建立一个宏AutoCar库,它包含许多宏的定义。这最适用于可重用宏,因此您不必在每个程序中重新定义它们。

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

其次,调用宏的位置无关紧要,只要您事先加载了宏即可

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

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

options sasautos=(sasautos mymacros) mautosource; 

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

%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
*/

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 ;
查看日志时要注意的事项:

  • 在%level3之外,&I返回宏变量不存在的警告 不存在
  • 在%level3中,调用&G1时,它返回存储在中的值 %level3的本地范围。一旦超出%level3,该值将返回 到全局存储的值

从技术上讲,自动调用库不会“提前”加载宏。如果用户试图执行宏,但该宏尚未定义,则SAS将开始在自动调用库中查找该宏。如果它成功地找到了与调用匹配的文件名,并且该文件包含与调用匹配的宏名称,则只有这样它才会编译宏。如果随后在自动调用库中对该文件进行更改,则需要手动重新提交代码,以使这些更改在交互式SAS会话中可用。
%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 ;