function - %SYSFUNC() 包装的连接函数在遇到括号时会出错
问题描述
我需要编写一个宏程序来生成一个用于移动平均计算的列表,我需要像这样构造一些行:
var1_ma_past_1=mean(var1, lag1(var1), lag2(var1), lag3(var1), lag4(var1), lag5(var1));
var1_ma_past_2=mean(lag1(var1), lag2(var1), lag3(var1), lag4(var1), lag5(var1), lag6(var1));
var1_ma_past_3=mean(lag2(var1), lag3(var1), lag4(var1), lag5(var1), lag6(var1), lag7(var1));
[...]
var2_ma_past_1=mean(var2, lag1(var2), lag2(var2), lag3(var2), lag4(var2), lag5(var2));
我的示例程序是
%macro test ;
%do i = 1 %to 5;
%let ln&i = ;
%do j = 1 %to 5;
%let dml = %str(,);
%let pos = %str(lag&i(var&j));
%let ln&j = %sysfunc(catx(&dml, &&ln&j, &pos));
%end;
%end;
/* example output */
%put &ln1;
%mend test;
%test
&j
不过,开始和结束值计划用参数替换。
输出是需要的&ln1
lag1(var1),lag2(var1),lag3(var1),lag4(var1),lag5(var1)
但对于&ln2
&ln3
等它不是(lag1(varn)
缺失)
lag2(var4),lag3(var4),lag4(var4),lag5(var4)
lag2(var3),lag3(var3),lag4(var3),lag5(var3)
此外,我得到了泛滥的日志输出,说ERROR: Required operator not found in expression:
这是因为里面的括号cats()
,这是里面的%sysfunc()
,复制这个的示例宏是
%macro test2;
%let x=meow;
%put %sysfunc(cats(x,lag()));
%mend;
%test2
我试图用 , 掩盖括号,%str
但没有奏效。%superq
%bquote
我想学习
- 的输出不正确的原因
&ln2
,&ln3
等等 - 修复它的原因
ERROR: Required operator not found in expression:
以及如何修复它(或解决方法,或者如果它不重要,甚至可以抑制错误)
提前致谢。
解决方案
无需在宏代码中使用 CAT...() 函数。
在用于连接值的宏代码中,您只需将它们彼此相邻展开。此外,您的逻辑似乎混淆了 I 和 J 计数器。
%macro test ;
%do i = 1 %to 5;
%let list = ;
%let dlm = ;
%do j = 1 %to 5;
%let list = &list.&dlm.lag&j(var&i) ;
%let dlm = ,;
%end;
%put &=i &=list;
%end;
%mend test;
%test
结果:
I=1 LIST=lag1(var1),lag2(var1),lag3(var1),lag4(var1),lag5(var1)
I=2 LIST=lag1(var2),lag2(var2),lag3(var2),lag4(var2),lag5(var2)
I=3 LIST=lag1(var3),lag2(var3),lag3(var3),lag4(var3),lag5(var3)
I=4 LIST=lag1(var4),lag2(var4),lag3(var4),lag4(var4),lag5(var4)
I=5 LIST=lag1(var5),lag2(var5),lag3(var5),lag4(var5),lag5(var5)
对于您的实际问题,您可能希望创建一个仅返回逗号分隔列表作为宏调用结果的宏。
%macro lags(varname,first,last);
%local lag dlm;
%do lag= &first %to &last ;
%if (&lag > 0) %then %*;&dlm.lag&lag(&varname);
%else %*;&dlm.&varname;
%let dlm=,;
%end;
%mend lags;
%put var1_ma_past_1=mean(%lags(var1,0,5));
%put var1_ma_past_2=mean(%lags(var1,1,6));
%put var1_ma_past_3=mean(%lags(var1,2,7));
%put var2_ma_past_1=mean(%lags(var2,0,5));
为什么您会收到这些错误消息:
%sysfunc()
宏函数需要尝试确定每个参数是字符还是数字,因为这样的函数可以CATX()
对任何一种类型的输入进行操作。这就是为什么()
in 参数值会混淆它,因为看起来您正在尝试传递数字表达式。
18 %put %sysfunc(catx(|,a(b),b));
ERROR: Required operator not found in expression: a(b)
a(b)|B
19 %put %sysfunc(catx(|,(1+2),b));
3|B
您可以强制在值周围加上引号,然后稍后将其删除(如果您的值实际上不包含引号)。
%let left=A(b);
%let right=b;
%let intermediate=%sysfunc(catx(|,"&left","&right"));
%let want=%sysfunc(compress(&intermediate,%str(%"));
%put &=want;
推荐阅读
- docker - 无法删除具有依赖子项的 docker 映像
- java - 发生 JNI 错误
- java - 如何在 onNext 调用中从上下文/范围中获取变量?(java/grpc)
- docker - 如何在 Docker 容器中打包单次使用的可执行文件?
- swift - Safari 应用程序扩展:Popover 中的 WKWebKit 未加载内容
- google-chrome - 在 Chrome@Windows 上为 google_debug.log 赋予有意义的名称
- sql - 在 SQL 中选择值计数为 1 的列标题
- ios - 如何调用 func renderer(_:didAdd:for:)
- javascript - 在 slideToggle 之后 HTML Canvas 高度默认为 1
- diagnostics - 在 CAPL 中获取诊断信息