为什么我的宏在调用execute()时表现不同?

时间:2014-12-09 09:57:22

标签: sas call sas-macro

使用SAS,我经常想对数据集的每一行执行操作。为此,我使用了在教程中找到的命令:call execute()。由于我对SAS环境不太熟悉,我倾向于使用宏功能来做任何我不知道如何使用call execute()执行它们的事情。 但是我很难理解宏语言在SAS中是如何工作的。我知道所有的宏引用都先被解析,这提供了一个base-SAS代码然后被执行(或者我已经错了?)。但我不明白它如何应用call execute()。 我们来考虑以下代码:

%macro prog1;    /* %prog1 defines a macrovariable mv1 */
%global mv1;
data _null_;
call symputx("mv1","plop");
run;
%mend;

%macro prog2(var);    /* prog2 puts it on the log */
%put PUT &var;
%mend;

%macro prog_glob;    /* prog_glob executes prog 1 then prog2 */
%prog1;
%prog2(&mv1);
%mend;

我知道这里不需要三个宏,但这是我的真实代码的最小版本,它具有这种结构。

现在,如果我执行prog_glob

%prog_glob;

我按预期在日志上获得PUT plop。 但是如果我将它与call execute()一起使用(即使这里不需要循环):

data _null_;
mac=%NRSTR("%prog_glob");
call execute(mac);
run;

我只获得PUT。 没有错误表明未定义macrovariable,因此%global语句有效。但不知何故,prog2prog1基础部分之前执行(至少我认为是这样)并且mv1尚未定义。

我的问题是:

  • 我的解释是否正确?
  • 当我使用call execute
  • 时,为什么结果会发生变化?
  • 根据先前的问题答案,我应该如何修复它?还是有更方便的方法来循环列值?

编辑:我的原始代码打算重命名我在数据集中列出的几个表的变量。对于每个列出的表,我希望执行以下算法:

  • prog1:将包含所有变量的列表存储在宏变量中(这是我定义mv等效的地方)
  • prog2:为这些变量名称
  • 添加一个公共后缀

可能有一种更聪明的方法可以做到这一点。我再也不熟悉SAS,而且我倾向于过度使用宏。如果你想告诉我一个更好的方法,我很乐意聊天,但我不希望你们重写我的所有代码,所以替代call execute就足够了我要感激不尽! :)

2 个答案:

答案 0 :(得分:2)

让我们看看文档 http://support.sas.com/documentation/cdl/en/mcrolref/61885/HTML/default/viewer.htm#a000543697.htm

如果EXECUTE例程参数是宏调用或解析为1,则宏立即执行。但是, EXECUTE例程生成的任何SAS语句在步骤边界传递之后才会执行

注意:由于宏引用会立即执行,并且SAS语句在步骤边界之后才会执行,因此不能使用CALL EXECUTE来调用包含由该宏中的CALL SYMPUT创建的宏变量的引用的宏。有关示例,请参阅与宏工具的接口。

这意味着,如果您通过调用execute:

调用它
  1. 立即执行宏语句 - 这些是:

    1.1。首先在%prog1:%global mv1; - 所以定义了mv1但是空,没有明显的...警告

    1.2。来自%prog1的SAS语句仍然是延期

  2. 现在%prog2 - 这里只有宏语句%PUT,它放置(仍为空)& mv1变量。那就是你在日志中看到的内容
  3. 现在所有立即执行的内容都已完成。包含调用执行的数据步骤结束。
  4. 现在正在执行从调用执行延迟的SAS语句:

    4.1。 prog1的数据集设置mv1的值。

  5. 这就是全部: - )

    编辑:关于您的修改:尝试查看此http://support.sas.com/kb/48/674.html

答案 1 :(得分:0)

data _null_;
mac='%nrstr(%prog_glob)';
call execute(mac);
run;

or, more plainly, as you would see in the documentation...

data _null_;
call execute('%nrstr(%prog_glob)');
run;

or

%let prog=%nrstr(%prog_glob);

data _null_;
mac="&prog.";
call execute(mac);
run;

or, and I wouldn't really recommend this one, but you could also manually concatenate the macro quotes

data _null_;
mac=cats('01'x,'%prog_glob','02'x);
call execute(mac);
run;

The way you are running it, the macro statements get execute at run time and the data step is execute after the calling data step completes. You're not properly using %NRSTR for this context, as described by the documentation. You need to pass the macro, along with the quoting as text to the call routine.