如何告诉 SAS 在每次调用时编译宏而不是手动执行
How to tell SAS to compile a Macro each time it is called instead of doing it manually
上下文: 我们使用 SAS 9.4
和 Enterprise Guide 7.15
。目前,我们正在实施一些新的宏,当然必须在此过程中进行很多更改。有时变化较小,有时变化较大。问题是,为了让更改生效,SAS
需要我们手动编译宏代码或重新启动会话,这有点乏味。
这是我们主文件(调用所有宏)中的当前设置:
/* Macro options */
MAUTOSOURCE sasautos = "<path to macro>" mlogic mlogicnest mprint mprintnest MRECALL
是否可以在使用 MAUTOSOURCE */ sasautos =""
选项时告诉 SAS
每次调用宏时实际上也编译宏而不是使用会话存储的宏?理想情况下,只有在执行主文件中的整行代码(MAUTOSOURCE */ sasautos =""
等)时才会编译宏,否则它应该在会话中保留编译版本。
我发现这个 paper (The Autocall Macro Facility in the SAS for Windows Environment) 在结论中指出
After that SAS will use the code that has already
been compiled. If changes are made to the macro, it must be
compiled again before the changes go into effect.
我希望这并不意味着我必须手动完成。有宏选项可以设置吗?
如果您从 WORK.SASMACR 中删除已编译的宏,当您再次调用它时,SAS 将不得不重新编译该宏。
proc catalog c=work.sasmacr;
*contents;
delete your-macro-to-recompile.macro;
run;
quit;
对于您的普通用户,您应该设置更改的发布时间表。用户将知道他们需要在发布后重新启动一个新会话。
对于正在测试所做更改的开发人员,他们只需要使用 %INCLUDE 重新编译宏。因此,如果您知道宏 XYZ 已更改,则只需 运行:
%include maclib('xyz.sas');
或者您可以暴力破解并重新编译自动调用库中的所有宏。
%incldue maclib('*.sas');
您可以更高级并制作一个宏来清除已编译宏的实际目录。类似于:
%macro clean_autocall;
proc catalog force c=work.sasmacr;
save clean_autocall /et=macro;
quit;
options mrecall mautosource;
%mend clean_autocall;
但是如果您使用的是企业指南,则有两个问题。
首先出于某种原因它使用不同的目录来存储编译的宏。 (为什么?)我认为是 WORK.SASMAC1 而不是 WORK.SASMACR.
第二个EG会手动编译一堆它需要的辅助宏。我不确定这些宏的完整列表是否有官方来源?您可以尝试将代码添加到项目中,以在项目启动时根据目录中的条目自动创建列表。这是我在 10 多年前尝试在生产环境中使用 EG 时制作的列表。但我确信它已经过时了。
%let s_eg_save= checkfmt checkhotfix
eclibassign eclibunassign enterpriseguide gaccessible
_eg_conditional_dropds
;
在 SAS 9.3 中,他们添加了 %SYSMACDELETE
宏函数。因此,如果您只想让自动调用重新定义单个宏,则使用它来删除当前定义。
%symacdelete mymacro;
这是一个实用程序宏,它将查询 SASHELP.VCATALG 视图以在 WORK 库中查找已编译的宏并将其删除。它可以选择列出要删除或保留的宏的名称。请注意,正常的 SAS 会话使用 WORK.SASMACR 来存储编译的宏。但是 SAS/Studio 和 EG(也许 运行 SAS 的其他方式)改用 WORK.SASMAC1。
https://github.com/sasutils/macros/blob/master/macdelete.sas
%macro macdelete(delete,keep);
/*----------------------------------------------------------------------------
Remove compiled macros using %SYSMACDELETE macro statement.
Use DELETE parameter to list macro names to delete.
Use KEEP parameter to list macro names to NOT delete.
Calling it with no values will delete all macros not currently running.
----------------------------------------------------------------------------*/
%local libname memname objname objtype fid i;
%do i=1 %to %sysmexecdepth;
%let keep=%sysmexecname(&i) &keep;
%end;
%if %length(&delete) %then %let delete=and findw("&delete",objname,',','sit');
%let fid=%sysfunc(open( sashelp.vcatalg(keep=libname memname objname objtype
where=(libname='WORK' and objtype='MACRO' and memname like 'SASMAC_'
and not findw("&keep",objname,',','sit') &delete))));
%if (&fid) %then %do;
%syscall set(fid);
%do %while(0=%sysfunc(fetch(&fid)));
%put %sysfunc(compbl(Removing &objname from &libname catalog &memname));
%sysmacdelete &objname;
%end;
%let fid=%sysfunc(close(&fid));
%end;
%else %put %qsysfunc(sysmsg());
%mend macdelete;
示例:
3348 %macro test1; %mend;
3349 %macro test2; %mend;
3350 %macro test3; %mend;
3351 %macro test4; %mend;
3352 %macdelete(test1 test3);
Removing TEST1 from WORK catalog SASMACR
Removing TEST3 from WORK catalog SASMACR
3353 %macdelete(keep=test2);
Removing TEST4 from WORK catalog SASMACR
示例 运行 SAS/Studio 或企业指南:
97 %macro test1; %mend;
98 %macro test2; %mend;
99 %macro test3; %mend;
100 %macro test4; %mend;
101 %macdelete(test1 test3);
Removing TEST1 from WORK catalog SASMAC1
Removing TEST3 from WORK catalog SASMAC1
上下文: 我们使用 SAS 9.4
和 Enterprise Guide 7.15
。目前,我们正在实施一些新的宏,当然必须在此过程中进行很多更改。有时变化较小,有时变化较大。问题是,为了让更改生效,SAS
需要我们手动编译宏代码或重新启动会话,这有点乏味。
这是我们主文件(调用所有宏)中的当前设置:
/* Macro options */
MAUTOSOURCE sasautos = "<path to macro>" mlogic mlogicnest mprint mprintnest MRECALL
是否可以在使用 MAUTOSOURCE */ sasautos =""
选项时告诉 SAS
每次调用宏时实际上也编译宏而不是使用会话存储的宏?理想情况下,只有在执行主文件中的整行代码(MAUTOSOURCE */ sasautos =""
等)时才会编译宏,否则它应该在会话中保留编译版本。
我发现这个 paper (The Autocall Macro Facility in the SAS for Windows Environment) 在结论中指出
After that SAS will use the code that has already been compiled. If changes are made to the macro, it must be compiled again before the changes go into effect.
我希望这并不意味着我必须手动完成。有宏选项可以设置吗?
如果您从 WORK.SASMACR 中删除已编译的宏,当您再次调用它时,SAS 将不得不重新编译该宏。
proc catalog c=work.sasmacr;
*contents;
delete your-macro-to-recompile.macro;
run;
quit;
对于您的普通用户,您应该设置更改的发布时间表。用户将知道他们需要在发布后重新启动一个新会话。
对于正在测试所做更改的开发人员,他们只需要使用 %INCLUDE 重新编译宏。因此,如果您知道宏 XYZ 已更改,则只需 运行:
%include maclib('xyz.sas');
或者您可以暴力破解并重新编译自动调用库中的所有宏。
%incldue maclib('*.sas');
您可以更高级并制作一个宏来清除已编译宏的实际目录。类似于:
%macro clean_autocall;
proc catalog force c=work.sasmacr;
save clean_autocall /et=macro;
quit;
options mrecall mautosource;
%mend clean_autocall;
但是如果您使用的是企业指南,则有两个问题。
首先出于某种原因它使用不同的目录来存储编译的宏。 (为什么?)我认为是 WORK.SASMAC1 而不是 WORK.SASMACR.
第二个EG会手动编译一堆它需要的辅助宏。我不确定这些宏的完整列表是否有官方来源?您可以尝试将代码添加到项目中,以在项目启动时根据目录中的条目自动创建列表。这是我在 10 多年前尝试在生产环境中使用 EG 时制作的列表。但我确信它已经过时了。
%let s_eg_save= checkfmt checkhotfix
eclibassign eclibunassign enterpriseguide gaccessible
_eg_conditional_dropds
;
在 SAS 9.3 中,他们添加了 %SYSMACDELETE
宏函数。因此,如果您只想让自动调用重新定义单个宏,则使用它来删除当前定义。
%symacdelete mymacro;
这是一个实用程序宏,它将查询 SASHELP.VCATALG 视图以在 WORK 库中查找已编译的宏并将其删除。它可以选择列出要删除或保留的宏的名称。请注意,正常的 SAS 会话使用 WORK.SASMACR 来存储编译的宏。但是 SAS/Studio 和 EG(也许 运行 SAS 的其他方式)改用 WORK.SASMAC1。
https://github.com/sasutils/macros/blob/master/macdelete.sas
%macro macdelete(delete,keep);
/*----------------------------------------------------------------------------
Remove compiled macros using %SYSMACDELETE macro statement.
Use DELETE parameter to list macro names to delete.
Use KEEP parameter to list macro names to NOT delete.
Calling it with no values will delete all macros not currently running.
----------------------------------------------------------------------------*/
%local libname memname objname objtype fid i;
%do i=1 %to %sysmexecdepth;
%let keep=%sysmexecname(&i) &keep;
%end;
%if %length(&delete) %then %let delete=and findw("&delete",objname,',','sit');
%let fid=%sysfunc(open( sashelp.vcatalg(keep=libname memname objname objtype
where=(libname='WORK' and objtype='MACRO' and memname like 'SASMAC_'
and not findw("&keep",objname,',','sit') &delete))));
%if (&fid) %then %do;
%syscall set(fid);
%do %while(0=%sysfunc(fetch(&fid)));
%put %sysfunc(compbl(Removing &objname from &libname catalog &memname));
%sysmacdelete &objname;
%end;
%let fid=%sysfunc(close(&fid));
%end;
%else %put %qsysfunc(sysmsg());
%mend macdelete;
示例:
3348 %macro test1; %mend;
3349 %macro test2; %mend;
3350 %macro test3; %mend;
3351 %macro test4; %mend;
3352 %macdelete(test1 test3);
Removing TEST1 from WORK catalog SASMACR
Removing TEST3 from WORK catalog SASMACR
3353 %macdelete(keep=test2);
Removing TEST4 from WORK catalog SASMACR
示例 运行 SAS/Studio 或企业指南:
97 %macro test1; %mend;
98 %macro test2; %mend;
99 %macro test3; %mend;
100 %macro test4; %mend;
101 %macdelete(test1 test3);
Removing TEST1 from WORK catalog SASMAC1
Removing TEST3 from WORK catalog SASMAC1