遍历宏变量并为其赋值问题
Iterating through macro variables and assinging values to them issue
我有以下宏:
%macro regex_builder;
%do i = 1 %to 11;
data _null_;
a = &i.;
call symputx('Var', a, 10.);
run;
proc sql noprint;
select Regex into :regex_string_&Var
from Regex
where monotonic() = &i.;
quit;
%put &®ex_string_&Var;
%end;
%mend;
%regex_builder;
这样做的目的是遍历数据集的行并将其中包含的值分配给一系列宏变量,即regex_string_1
、regex_string_2
等
当我使用 %put &®ex_string_&Var;
时,所需的数据被分配给某种宏变量,我得到了一系列正确顺序的宏变量字符串,并从我的源数据集中生成。
但是,当我尝试解析使用上述 regex_string_1
、regex_string_2
等命名约定创建的宏变量时,我收到一条警告,指出这些宏变量名称尚未声明。
我想知道的是:
1) 为什么我上面的代码没有按预期工作
2) 如何将上述由其他宏变量组成的宏变量名称的解析名称打印到SAS日志中?
谢谢
编辑:好的,在阅读了 Chris J 的回答后,我意识到问题实际上是什么 :)。
无论如何,我会把这段代码留在这里,因为它是做你想做的事情的更简单、更有效的方法。
在您的代码中,您需要调用 proc sql n 次,其中 n 是观察次数。事实上,您只需要一个数据步,根本不需要宏。请参阅下面的第 1 步:
data y;
input regex $;
datalines;
Hello
world
this
is
an
example
;
run;
/* 1) in the datasteps rows are looped automatically, no macro needed here */
data _null_;
set y;
call symputx(cats("regex_string_",_N_),regex);
run;
/* example */
%put ®ex_string_4;
proc sql noprint;
select count(*) into :n from y;
quit;
/* 2) This is how you refer to a macro variable by another macro variable */
%macro printall;
%do i = 1 %to &n;
%put &®ex_string_&i;
%end;
%mend;
%printall;
宏变量有一个 'scope',局部或全局。默认情况下,在宏中首次初始化的宏变量在范围内是局部的。这意味着您无法解析宏之外的值。
您可以 a) 最初在宏之外定义宏变量,或者 b) 在宏中将其指定为 %GLOBAL
。
%MACRO MYMACRO ;
%LET X = 1 ;
%MEND ;
%MYMACRO ;
%PUT &X ; /* not resolved as X is local to %MYMACRO */
/* Method A */
%LET X = ;
%MACRO MYMACRO ;
%LET X = Hello ;
%MEND ;
%MYMACRO ;
%PUT &X ; /* Resolves to Hello */
/* Method B */
%MACRO MYMACRO ;
%GLOBAL X ;
%LET X = Hello ;
%MEND ;
%MYMACRO ;
%PUT &X ; /* Resolves to Hello */
因此,要解决您的具体问题,只需添加
%GLOBAL &®ex_string_&Var ;
在您的 PROC SQL
步骤之前。
我有以下宏:
%macro regex_builder;
%do i = 1 %to 11;
data _null_;
a = &i.;
call symputx('Var', a, 10.);
run;
proc sql noprint;
select Regex into :regex_string_&Var
from Regex
where monotonic() = &i.;
quit;
%put &®ex_string_&Var;
%end;
%mend;
%regex_builder;
这样做的目的是遍历数据集的行并将其中包含的值分配给一系列宏变量,即regex_string_1
、regex_string_2
等
当我使用 %put &®ex_string_&Var;
时,所需的数据被分配给某种宏变量,我得到了一系列正确顺序的宏变量字符串,并从我的源数据集中生成。
但是,当我尝试解析使用上述 regex_string_1
、regex_string_2
等命名约定创建的宏变量时,我收到一条警告,指出这些宏变量名称尚未声明。
我想知道的是:
1) 为什么我上面的代码没有按预期工作 2) 如何将上述由其他宏变量组成的宏变量名称的解析名称打印到SAS日志中?
谢谢
编辑:好的,在阅读了 Chris J 的回答后,我意识到问题实际上是什么 :)。
无论如何,我会把这段代码留在这里,因为它是做你想做的事情的更简单、更有效的方法。
在您的代码中,您需要调用 proc sql n 次,其中 n 是观察次数。事实上,您只需要一个数据步,根本不需要宏。请参阅下面的第 1 步:
data y;
input regex $;
datalines;
Hello
world
this
is
an
example
;
run;
/* 1) in the datasteps rows are looped automatically, no macro needed here */
data _null_;
set y;
call symputx(cats("regex_string_",_N_),regex);
run;
/* example */
%put ®ex_string_4;
proc sql noprint;
select count(*) into :n from y;
quit;
/* 2) This is how you refer to a macro variable by another macro variable */
%macro printall;
%do i = 1 %to &n;
%put &®ex_string_&i;
%end;
%mend;
%printall;
宏变量有一个 'scope',局部或全局。默认情况下,在宏中首次初始化的宏变量在范围内是局部的。这意味着您无法解析宏之外的值。
您可以 a) 最初在宏之外定义宏变量,或者 b) 在宏中将其指定为 %GLOBAL
。
%MACRO MYMACRO ; %LET X = 1 ; %MEND ; %MYMACRO ; %PUT &X ; /* not resolved as X is local to %MYMACRO */ /* Method A */ %LET X = ; %MACRO MYMACRO ; %LET X = Hello ; %MEND ; %MYMACRO ; %PUT &X ; /* Resolves to Hello */ /* Method B */ %MACRO MYMACRO ; %GLOBAL X ; %LET X = Hello ; %MEND ; %MYMACRO ; %PUT &X ; /* Resolves to Hello */
因此,要解决您的具体问题,只需添加
%GLOBAL &®ex_string_&Var ;
在您的 PROC SQL
步骤之前。