%复制到宏变量

%copy to macro variable

我想将宏源代码的内容存储到一个变量中,以便稍后对其进行一些正则表达式处理。

假设我有以下宏函数:

%MACRO sleep
/*--------------------------------------
pauses for the desired amount of seconds
---------------------------------------*/ 
(sec
) / STORE SOURCE DES='pauses for the desired amount of seconds';
/* EXAMPLE:
%sleep(3);
*/
DATA _NULL_;
vVar1=SLEEP(%eval(&sec*1000));
RUN;
%mend;

我可以使用以下方法在日志中显示代码:

%copy sleep /source;

但是我希望能够写:

%let sleep_source = %get_source(sleep);

我的最终目标是能够提取示例(或测试)并执行以下操作:

%run_examples(sleep)
%run_tests(sleep)    # if I define tests in the function's body

使用 %COPY 宏的 OUTFILE= 选项。我的测试显示 OUTFILE 不喜欢成为 SOURCE 目录条目,因此此示例使用 WORK libref 文件夹中的外部文件。注意:%COPY 会覆盖现有的 OUTFILE。

libname mymacros 'c:\temp';
option mstored sasmstore=mymacros;

%MACRO sleep
/*--------------------------------------
pauses for the desired amount of seconds
---------------------------------------*/ 
(
  sec /* number of seconds to sleep */
) 
/ STORE SOURCE DES='pauses for the desired amount of seconds';
/* EXAMPLE:
%sleep(3);
*/
DATA _NULL_;
vVar1=SLEEP(%eval(&sec*1000));
RUN;
%mend;

filename extract "%sysfunc(pathname(work))\source-code.sas";

%copy sleep / outfile=extract source;

data _null_;
  infile extract;
  input;
  put _infile_;

  * do regex tests on the macros source code lines ;
  * ... ;
run;

%SLEEP:您可能并不总是希望宏创建具有步骤边界的代码。您可以
%sysfunc(sleep(%eval(&sec)*1000)) 代替。

为什么不直接使用自动调用宏呢?然后你可以创建一个指向你用于自动调用宏的相同路径的文件引用。因此很容易从包含它的实际文本文件中读取源代码。

filename mymacros '/path';
options sasautos=(mymacros);

data _null_;
  infile mymacros('sleep.sas');
  ...
run;

我修改了 Richard 的答案,将其包装成一个宏并从中获取一个宏变量。

我不是很满意,因为它创建了全局变量 src_code 和几个 _temp_outi,我不能用我想要的语法使用它,但它完成了工作。

%macro get_source(mac, line_sep = \n);
%global src_code;
filename extract "%sysfunc(pathname(work))\temp-source-code.sas";
%copy &mac / outfile=extract source;

data _null_;
  infile extract;
  input;
  call symput('_temp_out'||strip(_n_), _infile_);
  call symput('last_n', _n_);
run;

%let src_code = %superq(_temp_out1);
%do i = 2 %to &last_n;
  %let curr_var = _temp_out&i;
  %let src_code = &src_code&line_sep.%superq(&curr_var);
%end;
%mend;

我们来测试一下:

%get_source(sleep) /* creates a src_code global variable containing the source code */   
%put %superq(src_code);

将打印到日志:

%MACRO sleep\n/*--------------------------------------\npauses for the desired amount of 
seconds\n---------------------------------------*/ \n(sec\n) / STORE SOURCE;\n/* EXAMPLE:\n%sleep(3);\n*/\nDATA 
_NULL_;\nvVar1=SLEEP(%eval(&sec*1000));\nRUN;\n%mend;