关于sas:使用调用执行时的宏变量问题


Macro variables issue when using call execute

我在下面有 2 个宏,我正在尝试像使用元数据表的循环一样依次执行 1,并在数据步骤中调用执行命令。

macro %TWO 需要全局变量


您可以使用 %nrstr() 延迟宏调用,然后它就可以正常工作了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
   /* test data */
   data dataset;
     name="a"; condition="1"; output;
     name="b"; condition=""; output;
     name="c"; condition="1"; output;
   run;

   data a_agg; v="a_agg"; run;
   data b_agg; v="b_agg"; run;
   data c_agg; v="c_agg"; run;

   data meta_table;
     condition="1"; name_ot="ot1"; output;
     condition="2"; name_ot="ot2"; output;
     condition=""; name_ot="ot_"; output;
   run;

   %macro one(condition);
     %global names_agg;  
     %let names_agg = ;
     proc sql noprint;
       select cats(name,"_agg") into :names_agg separated by""
       from dataset where condition ="&condition.";
     quit;
   %mend;

   %*-- just checking --*;
   %one(condition=1) %put names_agg=&names_agg;
   %one(condition=2) %put names_agg=&names_agg;
   %one(condition= ) %put names_agg=&names_agg;
   %*-- on log
   names_agg=a_agg c_agg
   names_agg=
   names_agg=b_agg
   --*;


   %macro two(name_ot);
     %if &names_agg= %then %do;
       data &name_ot.; run;
     %end; %else %do;
       data &name_ot.;
         set &names_agg.;
       run;
     %end;
   %mend;

  data _null_;
      length code $200;
      set meta_table;
      code = catt('%one(', condition,")");
      code = catt(code, '%two(', name_ot,")");
      code = catt('%nrstr(', code,")");
      call execute(code);
   run;

   /* check */
   title ot1; proc print data=ot1; run; title;
   /* on lst
   ot1
   Obs      v
    1     a_agg
    2     c_agg
   */

   title ot2; proc print data=ot2; run; title;
   /* on log
   NOTE: No variables in data set WORK.OT2.
   */

   title ot_; proc print data=ot_; run; title;
   /* on lst
   ot_
   Obs      v
    1     b_agg
   */

您可能需要在数据步骤中将双引号更改为单引号,如下所示:

1
2
3
4
5
6
data _null_;
  length code $32767;
  set meta_table;
  code = '%ONE(' || cats(condition) || '); %TWO(' || cats(Name_OT) ||");";
  call execute(code);
run;

现在宏处理器正在尝试解析第 3 行中的百分比符号。您可以通过使用单引号隐藏它们来阻止它这样做。


除非您已经为您发布的示例从宏中削减了很多,否则很难理解为什么要使用两个宏而不是一个宏来执行此操作(或者实际上为什么您\\ '会使用宏来做到这一点)像这样:

1
2
3
4
5
6
7
8
9
10
11
%macro TheOnlyOne(condition,name_OT);
  proc sql noprint;
    select cats(name,"_agg")
    into :names_agg separated by""
    from dataset
    where condition="&condition";
  quit;
  data &name_OT;
    set &names_agg;
  run;
%mend;

无论如何,关于调用之间的宏变量发生了什么等问题,你尝试过吗

  • 在调用执行方法之外按顺序运行宏?
  • 在执行之前设置 options mprint mlogic symbolgen; 以查看日志中的调试信息?
  • 在您的宏中使用一些 %put 语句,并在您的 call execute 数据步中使用 put 语句,以便查看在各个点生成了什么?

建议在开发宏应用程序时首先让代码运行而不使用宏,然后添加宏变量并显式 %let-ting 其值,然后在宏的上下文中对其进行测试。之后将移至 call execute

也许尝试以上几点,然后返回一些我们可以调试的日志输出。您发布的代码中还有一些其他错误/问题,但我没有指出它们,而是假设您正在将其缩减为 SO 帖子。

顺便说一句,我喜欢使用 data _null_call execute 驱动数据驱动代码的想法,我经常使用这种方法。