更改 SAS 宏中宏变量的值

Changing Value of Macro Variable inside SAS macro

我正在宏中定义一个宏变量。然后,我将它输入第二个宏。内部 macro2 计数器将值更改为 200。但是,当我检查宏 2 运行后放入的宏变量中的内容时,它仍然显示 0。我希望它存储值 200?这可能吗?

 %macro macro1();
   %let variable1= 0;
   macro2(counter=&variable1)

   %put &variable1;
 %mend macro1;

 %macro1;

你有几个问题。首先,您在调用 macro2 之前缺少 %,但我怀疑这只是一个错字。主要问题是您正在尝试执行在其他语言中称为 call-by-reference 的操作。您可以在 SAS 宏中通过传递 变量的名称 而不是变量的值来执行此操作,然后使用一些时髦的 & 语法来设置该名称的变量到一个新值。

下面是执行此操作的一些示例代码:

%macro macro2(counter_name);
    /* The following code translates to:
    "Let the variable whose name is stored in counter_name equal
    the value of the variable whose name is stored in counter_name
    plus 1." */

    %LET &counter_name = %EVAL (&&&counter_name + 1);

%mend;

%macro macro1();
   %let variable1= 0;

   /* Try it once - see a 1 */
   /* Notice how we're passing 'variable1', not '&variable1' */
   %macro2(counter_name = variable1)
   %put &variable1;

   /* Try it twice - see a 2 */
   /* Notice how we're passing 'variable1', not '&variable1' */
   %macro2(counter_name = variable1)
   %put &variable1;
 %mend macro1;

 %macro1;

我实际上在 Whosebug 上有另一个 post,其中有对 &&& 语法的解释;你可以have a look at it here。请注意,%EVAL 调用与按引用调用无关,它只是用来做加法。

Sparc_Spread解释了如何在SAS宏语言中"call by reference",可能会解决你的问题。

虽然在这种特殊情况下,使用引用调用不一定很重要,我认为使用它并不是 SAS 宏语言的惯用方式(尽管它肯定没有错 - 它看起来有点奇怪,并且有点难,因为它不是真正的原生概念,但如果需要,肯定有意支持以这种方式使用)。有两种方法可以解决这个问题,而且都非常容易使用。

首先,假设您知道要递增的变量名,而起始值是唯一有趣的事情。由于 SAS 宏语言处理范围的方式,有些东西不完全是词法范围,也不完全是功能性的,它会自动使用已经存在于最局部范围的变量,当它已经存在时(有一些小的警告,例如宏使用DOSUBL).

所以这按预期工作:

%macro macro2(counter=);  
  %do variable1 =&counter. %to 200;
    %if %sysfunc(mod(&variable1.,50))=0 %then %put &=variable1;
  %end;

%mend macro2;

%macro macro1();
   %let variable1= 0;
   %macro2(counter=&variable1.);

   %put &=variable1;
 %mend macro1;

 %macro1;

(当然,如果您期望 &variable1 的值为 201 - 因为 %do 循环,如 do 循环,总是比它们的结束值增加一个。我假设您的实际程序会有所不同。)

那是因为 %macro2 中引用的 &variable1. 自动出现在最局部范围内 - 在本例中是 %macro1 的范围。


或者,如果您使用此 %macro2 来增加计数器,我会使用 function-style macro 方法。

根据定义,函数式宏是 return 只有一个值的宏 - returns 我的意思是在宏代码的末尾有一个值,显示在纯文本(因为宏毕竟只是用来创建文本,然后由普通的 SAS 语言解析器解析)。

这可以用在赋值语句中等号的右边。关键是它只使用宏语言元素 - %do 循环等 - 没有数据步骤、过程等语言会阻止它在赋值语句中位于等号右侧(即,x=%macrostuff(); 不能是 x=proc sql(select...)).

因此以下实现了目标:将计数器增加一些,return 值(201,在这种情况下,就像以前一样),然后可以将其分配给宏变量。

%macro macro2(counter=);  
  %do internal_counter =&counter. %to 200;
    %if %sysfunc(mod(&internal_counter.,50))=0 %then %put &=internal_counter.;
  %end;
  &internal_counter.
%mend macro2;

%macro macro1();
   %let variable1= %macro2(counter=0);

   %put &=variable1;
 %mend macro1;

 %macro1;

我建议这是完成此操作的最惯用的方法,也是最简单的方法:您将所需的值作为输入传递,函数对其进行操作,returns 值,然后您将其赋值随心所欲地添加到宏中的变量。