解析宏变量名称中包含 %eval 的宏,SAS
Resolving macro containing %eval in macro variable name, SAS
这是一个玩具示例,目的是帮助解决我遇到的一个更大的问题。它本质上涉及在引用更大的宏变量名称时使用 %eval() 宏。
我创建了一个宏变量x_2,它使用循环的值,'&it',从最终输出可以看出变量创建成功,但是我只能把它放到不评估 &it+1 的日志,当使用大于 1 的循环时我需要这样做。
似乎先解析 x_,发出警告,然后再整体评估 x_2 并给出输出。
我知道这只是一个关于如何正确引用宏的问题,但我找不到任何将求值用作宏变量名称的一部分的示例。
谢谢。
%macro testing;
%DO it = 1 %TO 1;
data dataset;
s=100;
t=99;
run;
data _null_;
set dataset;
if s = 100 then do;
call symput("x_%eval(&it+1)",t);
end;
run;
%put "&x_%eval(&it+1)";
%put &x_2;
%END;
%mend testing;
%testing;
日志输出
MLOGIC(TESTING): %PUT "&x_%eval(&it+1)"
WARNING: Apparent symbolic reference X_ not resolved.
SYMBOLGEN: Macro variable IT resolves to 1
SYMBOLGEN: Macro variable X_2 resolves to 99
" 99"
MLOGIC(TESTING): %PUT &x_2
SYMBOLGEN: Macro variable X_2 resolves to 99
99
MLOGIC(TESTING): %DO loop index variable IT is now 2; loop will not iterate again.
MLOGIC(TESTING): Ending execution.
你能试试"&&x_%eval(&it+1)"
吗?
把宏变量名建成另一个变量,然后展开值就容易多了
%let t2=found;
%let mvar=t%eval(1+1);
%put &&&mvar;
确实,SAS 在调用 %eval 函数之前进行了变量替换
最简单的解决方案是在较早的语句中调用 %eval
%let xNr = %eval(&it+1);
%put "&&x_&xNr";
双符号用于延迟 x_&xNr
的计算,直到 &xNr
被计算为 2
并且没有 x_
未定义的警告。
SYMBOLGEN: Macro variable IT resolves to 1
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable XNR resolves to 2
SYMBOLGEN: Macro variable X_2 resolves to 99
" 99"
同意德克的回答。但是作为一个思想练习,使用丑陋的引用函数是可以达到预期结果的:
%let x_2=99;
%let it=1;
%put %unquote(%nrstr(&x_)%eval(&it+1));
所以 %nrstr 隐藏 & 直到 %eval 完成它的工作(我认为。:)
更新:
@Shenglin 在评论中添加了一个我比上面的方法更喜欢的类似答案:
%put %superq(x_%eval(&it+1));
这是有效的,因为 %superq() 在将宏变量名作为参数(没有前导 &)而不是宏变量引用时很不寻常。所以你可以使用 %EVAL 生成宏变量名称的一部分。如果需要,您可以 %unquote() ,但这不是必需的。
这是一个玩具示例,目的是帮助解决我遇到的一个更大的问题。它本质上涉及在引用更大的宏变量名称时使用 %eval() 宏。
我创建了一个宏变量x_2,它使用循环的值,'&it',从最终输出可以看出变量创建成功,但是我只能把它放到不评估 &it+1 的日志,当使用大于 1 的循环时我需要这样做。
似乎先解析 x_,发出警告,然后再整体评估 x_2 并给出输出。
我知道这只是一个关于如何正确引用宏的问题,但我找不到任何将求值用作宏变量名称的一部分的示例。
谢谢。
%macro testing;
%DO it = 1 %TO 1;
data dataset;
s=100;
t=99;
run;
data _null_;
set dataset;
if s = 100 then do;
call symput("x_%eval(&it+1)",t);
end;
run;
%put "&x_%eval(&it+1)";
%put &x_2;
%END;
%mend testing;
%testing;
日志输出
MLOGIC(TESTING): %PUT "&x_%eval(&it+1)"
WARNING: Apparent symbolic reference X_ not resolved.
SYMBOLGEN: Macro variable IT resolves to 1
SYMBOLGEN: Macro variable X_2 resolves to 99
" 99"
MLOGIC(TESTING): %PUT &x_2
SYMBOLGEN: Macro variable X_2 resolves to 99
99
MLOGIC(TESTING): %DO loop index variable IT is now 2; loop will not iterate again.
MLOGIC(TESTING): Ending execution.
你能试试"&&x_%eval(&it+1)"
吗?
把宏变量名建成另一个变量,然后展开值就容易多了
%let t2=found;
%let mvar=t%eval(1+1);
%put &&&mvar;
确实,SAS 在调用 %eval 函数之前进行了变量替换 最简单的解决方案是在较早的语句中调用 %eval
%let xNr = %eval(&it+1);
%put "&&x_&xNr";
双符号用于延迟 x_&xNr
的计算,直到 &xNr
被计算为 2
并且没有 x_
未定义的警告。
SYMBOLGEN: Macro variable IT resolves to 1
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable XNR resolves to 2
SYMBOLGEN: Macro variable X_2 resolves to 99
" 99"
同意德克的回答。但是作为一个思想练习,使用丑陋的引用函数是可以达到预期结果的:
%let x_2=99;
%let it=1;
%put %unquote(%nrstr(&x_)%eval(&it+1));
所以 %nrstr 隐藏 & 直到 %eval 完成它的工作(我认为。:)
更新:
@Shenglin 在评论中添加了一个我比上面的方法更喜欢的类似答案:
%put %superq(x_%eval(&it+1));
这是有效的,因为 %superq() 在将宏变量名作为参数(没有前导 &)而不是宏变量引用时很不寻常。所以你可以使用 %EVAL 生成宏变量名称的一部分。如果需要,您可以 %unquote() ,但这不是必需的。