在SAS宏中改变宏变量的价值

时间:2015-06-15 20:22:48

标签: sas sas-macro

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

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

   %put &variable1;
 %mend macro1;

 %macro1;

2 个答案:

答案 0 :(得分:9)

这里有几个问题。首先,在致电%之前,您错过了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;

我实际上在StackOverflow上有另一篇文章,它解释了&&&语法;你可以have a look at it here。请注意,%EVAL调用与引用调用无关,只是在那里进行添加。

答案 1 :(得分:2)

Sparc_Spread解释了如何在SAS宏语言中“通过引用调用”,这可以解决您的问题。

在这种特殊情况下,使用引用调用并不一定是至关重要的,我认为使用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循环,总是增加一个高于它们的结束值。我假设你的真实程序的工作方式不同。)

这是因为&variable1.中引用的%macro2自动是最本地范围内的%macro1 - 在这种情况下是%macro2的范围。

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

根据定义,函数式宏只返回一个值 - 而%do我的意思是在宏的代码末尾有一个以纯文本形式显示的值(因为宏是毕竟,只打算创建将由普通SAS语言解析器解析的文本。)

然后可以在赋值语句中的等号右侧使用它。关键是它只使用宏语言元素 - x=%macrostuff();循环等 - 并且没有数据步骤,proc等等,这种语言会阻止它在赋值语句中位于等号的右侧(即,x=proc sql(select...)不能是%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; )。

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

>>> re.split("([a-zA-Z_])",li)
['', 'a', '123,145', 'B', ',12']

我建议这是实现这一目的最惯用的方法,也是最简单的方法:将所需的值作为输入传递,函数对其进行操作,返回值,然后将其分配给宏中的变量然而你要。