我在宏中定义一个宏变量。然后,我将它喂入第二个宏。在macro2计数器内部将值更改为200.但是,当我检查宏2变量运行后我放入的宏变量内部时,它仍然显示0.我希望它存储值200?这有可能吗?
%macro macro1();
%let variable1= 0;
macro2(counter=&variable1)
%put &variable1;
%mend macro1;
%macro1;
答案 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']
我建议这是实现这一目的最惯用的方法,也是最简单的方法:将所需的值作为输入传递,函数对其进行操作,返回值,然后将其分配给宏中的变量然而你要。