SAS-将字符串宏变量附加到数据集名称

SAS-将字符串宏变量附加到数据集名称,sas,Sas,我试图在SAS中向数据集名称追加一个字符串宏变量。我想创建类似于work.cps2020jan和work.cps2020feb的数据集。但这不是我得到的。我的代码: %macro loop(values); %let count=%sysfunc(countw(&values)); %do i = 1 %to &count; %let value=%qsc

我试图在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的数据集。如果我改变了价值观。到&i。SAS输出work.cps20201和work.cps20202。但那不是我想要的


任何细节?

将按
%qscan()
引用的方式返回。改用
%scan()
。以这种方式使用时,引用的宏变量有时会导致分辨率问题。最好只在需要时引用它们,例如在
%put
语句中,语句中有一个%符号。

您不需要
%qscan()
。如果该值包含任何需要宏引号的字符,则它们在成员名称中无论如何都是无效的。因此,请改用
%scan()

但是,当在宏中使用时,即使在
&mvar
中没有特殊字符,标记器有时也会错误地将类似于
xxx&mvar
的内容视为两个标记。您可以对生成的值进行分组以解决该问题

例如,创建一个新的宏变量

%let dsn=cps2020&value.;
data work.&dsn. ;
或者使用
%unquote()
函数:

data %unquote(work.cps2020&value.);
或使用名称文字:

data work."cps2020&value."n;

%QSCAN
宏函数将使用仅对宏处理器系统可见的特殊不可见(不可打印)字符屏蔽其结果

发生了什么事

data work.cps2020&value.;
被视为

data work.cps2020<mask-character><non-masked part of symbol value><mask-character>;  
可以使用
%put\u 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
    宏%quote开始
  • 08
    宏%quote结束
  • 01
    宏%str开始
  • 02
    宏%str结束
  • 1E
    逗号的屏蔽版本

非常好的解释哇-太好了,谢谢!在将qscan()替换为scan()之后,宏完成了我希望它执行的操作(循环遍历字符串列表并将字符串附加到数据集名称)。
%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;