循环一组宏
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);
我想创建一个循环,这样我 运行 每个数据集都有两个宏
%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);