生成 SAS 宏代码而不执行它

Generate SAS macro code without executing it

有没有一种方法可以在不执行宏的情况下打印宏生成的 SAS 代码?

谢谢

不,一般不会。宏是生成 SAS 代码的程序,因此了解它将生成什么代码的唯一方法是 运行 它。在一些非常简单的情况下,您可能能够解析宏并确定将生成什么 SAS 代码,但对于任何更复杂的情况,您必须重新实现一个程序来读取、解析和执行这个宏上班。另见 the Halting Problem

有几种方法可以达到你想要的效果,至少在某些时候是可行的。

您可以设置 options obs=0; 然后 运行 宏(MPRINT 开启)。这将 运行 宏但不会处理任何数据行。这适用于许多宏;但它会覆盖数据集,所以如果你关心它正在写的东西而不是被保留,那是不安全的。

%macro do_something;
  data test;
    set sashelp.class;
  run;
%mend do_something;

options mprint;
options obs=0;

%do_something;

WORK.TEST 被覆盖,请注意,但未处理任何观察结果。

现在,如果您谈论的是存储的编译宏(这似乎是最有用的情况,不是吗?),那么这取决于它是如何存储的。如果它是用 /source 开关存储的,那么你可以用 %COPY.

取回源
libname sasdir "e:\temp"; 
options mstored sasmstore=sasdir; 

%macro do_something/store source;
  data test;
    set sashelp.class;
  run;
%mend do_something;

%copy do_something/source;

不过,它要求编译时带有 source 标志。如果不是,那么在 运行 编译代码之前无法恢复源代码。

还有一种方法,如果你的宏主要是数据步骤和过程sql,就是使用run cancel;proc sql noexec;选项,例如:

%macro example(somelogic=1,execute=NO);

  %local cancel noexec;
  %if &execute=NO %then %do;
    %let cancel=cancel;
    %let noexec=noexec;
  %end;

  data some_ds;
    set some_other_ds;
  %if &somelogic %then %do;
    this=that;
  %end;
  run &cancel;

  proc sql &noexec;
  create table maybe as 
    select * from have;

%mend;

通过这种方式,您的代码将被生成/语法检查但不会被执行。

当然 - 这是一种 'handle with care' 方法,因为在宏观环境中仍然有很多事情可以改变。 @Chris Long 是正确的 - 没有可靠的方法可以在不执行 SAS 代码的情况下生成它(因为生成的实际代码通常取决于早期执行的结果)。

您可以尝试使用 PROC STREAM。 让我们定义一个简单的宏

%macro mymacro;
 proc print data=sashelp.class; run;
%mend;

制作一个 fileref 以包含结果代码

filename mycode temp;

现在您可以使用PROC STREAM将宏调用转换为文本。

proc stream outfile=mycode; BEGIN
%mymacro
;;;;

它应该适用于任何不需要根据它生成的代码的结果做出决定的宏。