Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Loops SAS中调用执行宏脚本中的动态变量_Loops_Macros_Sas - Fatal编程技术网

Loops SAS中调用执行宏脚本中的动态变量

Loops SAS中调用执行宏脚本中的动态变量,loops,macros,sas,Loops,Macros,Sas,我有一个宏,它将生成一个包含prod列和另外12列的数据集。我还有一个表prodincl_fr,其中包含下面的示例数据集 Rownum prodcat ---------- 1 L 2 L1 3 M 4 LM ... ... 我想做一个do-until循环,它将调用宏%runlimitsquery,并在每次迭代中使用prodcat的值 我不知道如何在SAS中编写这个。我正在按照下面的代码玩。注:reccount=产品包含的行数 data _null

我有一个宏,它将生成一个包含prod列和另外12列的数据集。我还有一个表prodincl_fr,其中包含下面的示例数据集

Rownum prodcat
----------
1      L
2      L1
3      M
4      LM
...    ...
我想做一个do-until循环,它将调用宏%runlimitsquery,并在每次迭代中使用prodcat的值

我不知道如何在SAS中编写这个。我正在按照下面的代码玩。注:reccount=产品包含的行数

data _null_;
set prodincl_fr;
do until(rownum=reccount);
  prod=prodcat;
  call execute('%nrstr(%runlimitsquery(&prod))');
  output;
end;
run;

希望你能帮助我。求你了

您的代码有几处错误

  • reccount
    不是
    producl\u fr
    数据集的变量,因此不存在于该数据步骤的上下文中。因此,
    do
    语句等同于
    do-until(rownum=)
  • 您正在为数据集中的每条记录调用该循环。因此,在该循环的整个迭代过程中,rownum的值永远不会改变,并且将保持当前观察中的rownum值。您的
    until
    条件将永远不会满足,您的代码将永远运行
  • &prod
    是对宏变量的引用。但是,当您在
    数据
    步骤中写入
    prod=prodcat
    时,您创建的是数据步骤变量,而不是宏变量。因此,
    &prod
    不存在
  • 即使存在
    prod
    宏变量,也不会解析它,因为对它的引用包含在单引号中。SAS不尝试解析单引号字符串中的宏代码/引用。你需要使用双引号
该代码在语法上是正确的,如下所示:

然而,如果producl\u fr包含1000条记录,那么该操作将如下所示:您的数据步骤将转到
producl\u fr
的第一条记录,启动循环,使用与当前记录的
prod
相同的值调用宏一千次;然后,它将转到第二条记录,并使用该记录的prodcat值再次调用宏一千次;以此类推,直到第一千个记录

因为我假设这不是您要寻找的,并且因为带有
set
语句的数据步骤隐式地迭代所有记录,所以您可以取消do循环,并像这样编写数据步骤:

data _null_;
set prodincl_fr;
call execute('%runlimitsquery('||prodcat||');');
run;

如果已知的codegen数量少于64K个字符,则可以使用SQL准备宏调用。我发现这种风格的codegen对读者来说特别清晰

%macro runlimitsquery(prodcat);
  %put &sysmacroname called with &=prodcat;
%mend;

data prodcats;
  input prodcat $ @@;
datalines;
auto boat home flood aux worker life
run;

proc sql noprint;
  select 
    cats('%runlimitsquery(',prodcat,')')
  into
    :invoker separated by ' '
  from
    prodcats
  ;
quit;

%put NOTE: invoker=%superq(invoker); * lets see what is going to be invoked (the codegen);

* invoke the codegen;
&invoker
日志的最后部分

134  %put NOTE: invoker=%superq(invoker); * lets see what is going to be invoked (the codegen);
NOTE: invoker=%runlimitsquery(auto) %runlimitsquery(boat) %runlimitsquery(home)
%runlimitsquery(flood) %runlimitsquery(aux) %runlimitsquery(worker) %runlimitsquery(life)
135
136  * invoke the codegen;
137  &invoker
RUNLIMITSQUERY called with PRODCAT=auto
RUNLIMITSQUERY called with PRODCAT=boat
RUNLIMITSQUERY called with PRODCAT=home
RUNLIMITSQUERY called with PRODCAT=flood
RUNLIMITSQUERY called with PRODCAT=aux
RUNLIMITSQUERY called with PRODCAT=worker
RUNLIMITSQUERY called with PRODCAT=life

如果codegen将超过64k个字符,您可能需要后退一步,重新思考手头任务的内容和方式。

我将继续使用%nrstr()环绕宏调用,就像在OP中一样。这些堆栈将在数据步骤完成后发生所有%runlimitsquery宏调用。| |字符串串接是可以的,但是如果数据集变量很长,可能会导致一些不可靠的日志记录。考虑使用CATSH()来连接数字和字符数据。最后,宏调用并不总是需要尾随分号。是否取决于宏所做的事情、调用的上下文、任何副作用文本的上下文以及运行时的上下文,我也会尝试这个。谢谢你,理查德!
134  %put NOTE: invoker=%superq(invoker); * lets see what is going to be invoked (the codegen);
NOTE: invoker=%runlimitsquery(auto) %runlimitsquery(boat) %runlimitsquery(home)
%runlimitsquery(flood) %runlimitsquery(aux) %runlimitsquery(worker) %runlimitsquery(life)
135
136  * invoke the codegen;
137  &invoker
RUNLIMITSQUERY called with PRODCAT=auto
RUNLIMITSQUERY called with PRODCAT=boat
RUNLIMITSQUERY called with PRODCAT=home
RUNLIMITSQUERY called with PRODCAT=flood
RUNLIMITSQUERY called with PRODCAT=aux
RUNLIMITSQUERY called with PRODCAT=worker
RUNLIMITSQUERY called with PRODCAT=life