我试图将一个字符串宏变量附加到SAS中的数据集名称中。我想要创建读取类似work.cps2020jan和work.cps2020feb的数据集。但这不是我想要的。我的代码:
%macro loop(values);
%let count=%sysfunc(countw(&values));
%do i = 1 %to &count;
%let value=%qscan(&values,&i,%str(,));
%put &value;
data work.cps2020&value.;
set "A:\cpsb2020&value" ;
mth = "&value.";
keep
PEMLR
mth
;
run;
%end;
%mend;
%loop(%str(jan,feb));
运行此代码将在日志中产生以下输出:
NOTE: There were 138697 observations read from the data set
A:\cpsb2020jan.
NOTE: The data set WORK.CPS2020 has 138697 observations and 2 variables.
NOTE: The data set WORK.JAN has 138697 observations and 2 variables.
NOTE: DATA statement used (Total process time):
real time 4.29 seconds
cpu time 0.20 seconds
feb
NOTE: There were 139248 observations read from the data set
A:\cpsb2020feb.
NOTE: The data set WORK.CPS2020 has 139248 observations and 2 variables.
NOTE: The data set WORK.FEB has 139248 observations and 2 variables.
NOTE: DATA statement used (Total process time):
real time 4.44 seconds
cpu time 0.15 seconds
我不明白为什么我的宏每个循环创建两个数据集,而不是每个循环创建一个数据集,名为work.cps2020jan和work.cps2020feb。如果我改变了&价值。to &I.SAS输出work.cps20201和work.cps20202。但这不是我想要的。
有什么见解吗?
发布于 2020-12-11 23:40:19
%QSCAN
宏函数将用只对宏处理器系统可见的特殊不可见(不可打印)字符掩盖其结果。
所发生的是
data work.cps2020&value.;
被视为
data work.cps2020<mask-character><non-masked part of symbol value><mask-character>;
在执行器处理过程中,它将不可打印的掩码字符视为非语法令牌分隔符,从而生成一个DATA
语句,列出两个输出表。
data work.cps2020 jan;
可以使用%put _user_
(在日志中)观察到掩码字符在宏变量中的位置,或者可以从元数据视图(如SASHELP.VMACRO
或DICTIONARY.MACRO
)捕获实际的符号内容。
让我们简化宏,并添加一些日志记录和符号捕获
%macro loop(values);
%local count i;
%let count=%sysfunc(countw(&values));
%do i = 1 %to &count;
%let value=%qscan(&values,&i,%str(,));
%put _user_; %*--- log them masks;
data x&i; %* --- symbol capture;
set sashelp.vmacro;
where name like '%VALUE%';
value_hex = put (value,$HEX40.);
run;
%* --- do the step that creates two tables;
data work.cps2020&value.;
set sashelp.class;
run;
%end;
%mend;
options nomprint nosymbolgen nomlogic;
%loop(%str(jan,feb));
proc print data=x1 noobs style(data)=[fontsize=14pt fontfamily="Courier"];
var value:;
run;
日志片段,这些小框是特殊的隐形掩蔽字符(我在图像捕获中显示它们,因为堆栈溢出/ html不会显示不可打印的字符)
相同的日志文本、复制和粘贴到Notepad2中将掩码字符显示为控制字符。
捕获的宏符号数据的Proc PRINT
将公开十六进制掩蔽字符。
06
宏%引用start08
宏%引用end01
宏%str start02
宏%str end1E
蒙版逗号发布于 2020-12-11 12:37:25
&value
按%qscan()
引用的方式返回。使用%scan()
代替。引用的宏变量有时会在以这种方式使用时引起问题的解决。最好只在需要时引用它们,例如在其中包含%签名的%put
语句中。
发布于 2020-12-11 14:03:29
你不需要%qscan()
。如果该值包含需要宏引用的任何字符,则无论如何它们在成员名称中使用都是无效的。所以使用%scan()
代替。
但是,当在宏中使用时,即使在xxx&mvar
中没有特殊字符的情况下,令牌程序有时也会错误地将像&mvar
这样的东西看作两个令牌。您可以将正在生成的值分组以解决此问题。
例如,通过创建一个新的宏变量
%let dsn=cps2020&value.;
data work.&dsn. ;
或者使用%unquote()
函数:
data %unquote(work.cps2020&value.);
或者使用名称文字:
data work."cps2020&value."n;
https://stackoverflow.com/questions/65257478
复制