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

  • 本文关键字:execute 调用 sas call sas-macro
  • 更新时间 :
  • 英文 :


使用 SAS,我经常想对数据集的每一行执行操作。为此,我使用在教程中找到的命令:call execute() 。由于我对SAS环境不是很熟悉,所以我倾向于使用宏函数来做任何我不知道如何做的事情,并用call execute()执行它们。但是,我很难理解宏语言在SAS中的工作原理。我知道首先解析所有宏引用,它提供了一个基本 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.没有错误表明宏变量未定义,因此 %global 语句有效。但不知何故,prog2是在基础部分之前执行prog1(至少我认为是这样(,mv1尚未定义。

我的问题是:

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

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

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

可能有一种更聪明的方法可以做到这一点。同样,我对 SAS 不太熟悉,我倾向于过度使用宏。如果你想向我展示一种更好的方法来做到这一点,我很乐意聊天,但我不希望你们重写我的所有代码,所以call execute的替代方案就足以让我感激!:)

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

如果 EXECUTE 例程参数是宏调用或解析为宏调用,则宏将立即执行。但是,在通过步骤边界之前,由 EXECUTE 例程生成的任何 SAS 语句都不会执行

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

这意味着,如果您通过调用执行调用它:

  1. 宏语句立即执行 - 它们是:

    1.1. %prog1 中的第一个: %global mv1; - 所以 mv1 已定义但为空,没有明显的...警告

    1.2. 来自 %prog1 的 SAS 语句仍处于延迟状态

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

    4.1. PROG1 中的数据集为 MV1 设置值。

仅此而已:-(

编辑:

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

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

或者,更直白地说,正如您在文档中看到的那样......

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

%let prog=%nrstr(%prog_glob);
data _null_;
mac="&prog.";
call execute(mac);
run;

或者,我真的不推荐这个,但您也可以手动连接宏引号

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

运行它的方式,宏语句在运行时执行,数据步骤在调用数据步骤完成后执行。 未正确将 %NRSTR 用于此上下文,如文档中所述。 您需要将宏以及引用作为文本传递给调用例程。

最新更新