生成 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
;;;;
它应该适用于任何不需要根据它生成的代码的结果做出决定的宏。
有没有一种方法可以在不执行宏的情况下打印宏生成的 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
;;;;
它应该适用于任何不需要根据它生成的代码的结果做出决定的宏。