HOPEWELL的解答:
data one;
input x @@;
datalines;
1 1 1
;
data two;
input x y @@;
datalines;
2 3 2 3 2 3
;
data three;
input x y z @@;
datalines;
4 5 6 4 5 6 4 5 6
;
%macro test/parmbuff;
options mcompilenote=none nomprint nosymbolgen nomlogic;
data %scan(&syspbuff,1); run;
%let n=2;
%let dsname=%scan(&syspbuff,&n);
%do %while(&dsname ne);
%let dsid=%sysfunc(open(&dsname,i));
%let varname=%sysfunc(varname(&dsid,%sysfunc(attrn(&dsid,nvars))));
%let rc=%sysfunc(close(&dsid));
%put &dsname &varname;
data out;
merge out &dsname(keep=&varname);
run;
%let n=%eval(&n+1);
%let dsname=%scan(&syspbuff,&n);
%end;
%mend;
%test(out one two three)
这个解答很精彩,也很难让一般人看的清楚明白,我来解释一下:
思路:首选用一个自动宏变量syspbuff获取%test(out one two three)宏中的文本参数 (out one two three),至于像了解syspbuff这个宏变量的含义,去找SAS官网看看。
用一个%scan截取文本参数的字符串,作为后面的数据集的名称。这里有段解释也许有用:
SYSPBUFF resolves to the text supplied as parameter values in the invocation of a macro that is defined with the PARMBUFF option. For name-style invocations, this text includes the parentheses and commas. Using the PARMBUFF option and SYSPBUFF, you can define a macro that accepts a varying number of parameters at each invocation. If the macro definition includes both a set of parameters and the PARMBUFF option, the macro invocation causes the parameters to receive values and the entire invocation list of values to be assigned to SYSPBUFF.
这里有个难点就是%do %while(&dsname ne);其实应该晓得&dsname ne的返回结果要么是true,要么是false.那么NE是比较什么呢?这里其实就是确定不同N下,通过%SCAN得到的DSNAME宏变量是否存在,也就是后面的DSNAME对应的数据集是否存在,读者可以做一个测试,第一:将数据集TWO去掉看看是提示LOG;第二:在文本参数中后面加一个four,看看错误提示,这个是我的理解。
在这个里面还涉及到三个函数,一个OPEN,一个是VARNAME, 一个ATTRN,OPEN函数其实就是打开制定的数据集DSNAME,ATTRN其实是获得当前活动状态下数据集DSNAME的变量数这一属性值,然后VARNAME获得在当前活动状态下数据集DSNAME里面的最后一个变量(加入变量数这属性值为3,那么就是获得第三个变量,及最后一个变量)。然后关闭活动状态下的数据集DSNAME。N自动加1,继续循环。知道(&dsname ne)为false。
不知道解释清楚没得,这个程序很经典,很多宏书上都有这个示例,大家可以琢磨一下。(多谢soporaeternus 提出来) |