循环一组宏

Looping a set of Macros

我想创建一个循环,这样我 运行 每个数据集都有两个宏

%Let Classification  = Data1 data2 data3 data4; 

%let index  = 1;

%do %until (%Scan(&Classification,&index," ")=);

%Macro1;
%Macro2;

%end;

%let index  = %eval(&Index  + 1);

问题是我的宏没有预加载,而是存储在宏库中,如果我 运行 上面的宏可以做到这一点吗?

任何有助于使这个宏循环工作的建议都非常感谢

编辑:

在我的理想情况下,循环会 运行 像一个宏

%Macro;

里面的样子

%Macro Macro;

%let index = 1;

%do %until (%scan(&classification,&index," ")=);

<Lines of Code>

%end;

%let index = %eval(&Index + 1);

%end;

%mend;

另一个问题是我在循环中包含的宏使用 &classification 来区分 data1、data2、data3、data4,因为我们处理不同的代码行。

自动调用库中的宏(我假设您指的是什么?)对上述方法的工作方式没有任何影响。如果它不在自动调用库中,您必须先将目录连接到自动调用库。

关于:您的编辑;是的,你需要把它放在一个宏中(我假设它最初是宏的一个子集)。 %do 当前不允许在开放代码中使用(这可能会改变,但不是今天)。

请注意,您的代码中存在几个重要问题:

  • 增量器不在循环中
  • 扫描功能错误;宏语言不使用引号,所以

    %do %until (%Scan(&Classification,&index," ")=);

    需要

    %do %until (%Scan(&Classification,&index)=);

    (space 是默认分隔符),如果你真的需要澄清 space:

    %do %until (%Scan(&Classification,&index,%str( ))=);

  • 您的宏没有使用参数;他们应该。 %macro1; 显然使用 &classification&index;相反,你应该将你想要的东西(来自 &classification 的 "word")作为参数传递给它。

SAS 不允许在开放代码中使用 %DO 语句。当您提交一个开放的代码循环时,您将收到日志消息

ERROR: The %DO statement is not valid in open code.
...
ERROR: The %END statement is not valid in open code.

正如@Tom 提到的,宏 %SCAN 测试应该检查空字符串。另一种常见且更可靠的方法是在令牌提取之前进行检查。 %do %until 传递的分类为空时会迭代很差。 %do %while 在内部宏调用之前测试 classification 扫描。空宏值的另一个常见测试是检查 0 长度并利用 0=false ^0=true 自动评估。

当循环使用令牌值调用其他宏时,最佳做法是传递令牌值,而不是让被调用的宏假定令牌符号(又名宏变量)已经存在(在包含范围内)之前迭代的宏调用。

示例

%macro mydispatch (classification=);

  %local index token;
  %let index = 1;
  %do %while ( %length (%scan (&classification, &index)));
    %let token = %scan(&classification,&index));

    %* emit code specifically for token;
    * this is for &token;

    %* iterated invocations, perform two analysis for each data set listed in classification;        
    %* second analysis is passed another argument specifying the data set that should be used to store output;
    %analysis_1 (data=&token)
    %analysis_2 (data=&token, out=WORK.results_&token.)

    %let index = %eval(&index+1);
  %end;
%mend mydispatch;

%mydispatch (classification=data1 data2 data3 data4)

迭代索引可能更容易。使用 countw() 函数查找要执行的迭代次数。

%macro loop(list);
%local index next ;
%do index=1 %to %sysfunc(countw(&list,%str( )));
  %let next=%scan(&list,&index,%str( ));
  ... code to process &NEXT ...
%end;
%mend ;

然后将列表作为参数值传入宏

%Let Classification  = Data1 data2 data3 data4; 
%loop(&classification);