循环一组宏

时间:2018-04-30 14:37:43

标签: sas sas-macro

我希望创建一个循环,以便为每个数据集运行两个宏

%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;

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

3 个答案:

答案 0 :(得分:3)

迭代索引可能更容易。使用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);

答案 1 :(得分:2)

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扫描。 null宏值的另一个常见测试是检查0长度并利用0 = false ^ 0 =真正的自动评估。

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

示例

%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)

答案 2 :(得分:1)

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

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

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

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

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

    需要

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

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

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

  • 您的宏不使用参数;他们应该。 %macro1;显然使用&classification&index;相反,你应该把你想要的东西(&#34;单词&#34;来自&classification)作为参数传递给它。