【问题标题】:SAS V9.1.3 - Error when combining %INC and CALL EXECUTESAS V9.1.3 - 组合 %INC 和 CALL EXECUTE 时出错
【发布时间】:2011-01-23 04:23:09
【问题描述】:

我收到一些 SAS v9.1.3 代码的解析错误。

这是一些我想存储在 .txt 文件中的代码(称为 problem2.txt)并使用 %INC 导入 SAS

%macro email020;                  
   %if &email = 1 %then %do;       
     %put THIS RESOLVED AT 1;      
   %end;                           
   %else %if &email = 2 %then %do; 
     %put THIS RESOVLED AT 2;      
   %end;                           
   %put _user_;                    
%mend email020;                   

%email020; 

那么这是主要代码:

filename problem2 'C:\Documents and Settings\Mark\My Documents\problem2.txt';

%macro report1;                            
  %let email = 1;
  %inc problem2;
%mend report1;                             

%macro report2 (inc);                            
  %let email = 2;                          
  %inc problem2;
%mend report2;                             

data test;                                 
  run = 'YES';                             
run;                                       

data _null_;                               
  set test; 
  call execute("%report1");  
  call execute("%report2");  
run;

日志显示:

NOTE: CALL EXECUTE generated line.
1   +  %inc problem2;
MLOGIC(EMAIL020):  Beginning execution.

WARNING: Apparent symbolic reference EMAIL not resolved.

ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: &email = 1

ERROR: The macro EMAIL020 will stop executing.

MLOGIC(EMAIL020):  Ending execution.

所以问题是为什么 CALL EXECUTE 生成 %inc problem2 而不是 %report1,导致 SAS 错过分配,我该怎么办?

【问题讨论】:

    标签: include macros sas execute


    【解决方案1】:

    %include 不是宏调用,而是一种编译器指令,用于包含来自外部文件的代码。编译宏%report1 时,没有宏变量email(因为该宏之前从未运行过),因此引用保持原样,&email。然后隐含的%eval() 看到&email = 1 并抱怨,因为看起来您正在将文本(&email)与数字(1)进行比较。

    尽可能避免引入%global。我会完全取消%include。更简单,下面是。 :-)

    %macro doSomething(email=);                  
      %if &email = a@b.c %then %do;       
        %put THIS RESOLVED AT 1;      
      %end; %else %if &email = d@e.f %then %do; 
        %put THIS RESOVLED AT 2;      
      %end;                           
      %put _user_;                    
    %mend doSomething;                   
    
    
    data emails;
      email="a@b.c"; output;
      email="d@e.f"; output;
    run;
    
    data _null_;
      set emails;
      call execute(catx(email, '%doSomething(email=', ')'));
    run;
    
    /* on log
    THIS RESOLVED AT 1
    DOSOMETHING EMAIL a@b.c
    THIS RESOVLED AT 2
    DOSOMETHING EMAIL d@e.f
    */
    

    【讨论】:

    • Chang Chung,非常感谢您的回复。对于延迟回复我深表歉意:在过去的 2.5 周里,我一直因猪流感而卧床不起。 '重视您的反馈,并将您的想法添加到此处的代码中。干杯,马克
    【解决方案2】:

    这似乎是一个宏变量范围问题。试试:

    %macro report1;   
      %global email; 
      %let email = 1;
      %inc problem2;
    %mend report1;                             
    
    %macro report2;            
    %global email; 
      %let email = 2;                          
      %inc problem2;
    %mend report2;                             
    

    但是,我认为将email 作为参数传递给%email020 而不是使用全局宏变量会更好。另外,我会避免使用嵌套的宏定义。

    要获取有关宏变量范围的更多数据,您可以在宏执行期间查询 dictionary.macros 视图。您可以使用

    获取dictionary.macros的描述
    proc sql;
        describe table dictionary.macros;
    quit;
    

    【讨论】:

    • 嗨 Ville - 感谢您的回复。关于范围问题,您绝对是正确的。我想我无法理解的是为什么可变分辨率的“正常”方法似乎没有发生。 “正常”的意思是如果内部宏在其本地符号表上找不到对宏变量的引用,它会自动搜索外部符号表以查看它是否分配到其他地方,向上移动到全局符号表(如我我确定你知道)。由于 EMAIL 是在外部宏中分配的,我认为当内部宏执行时找不到它时,应该在它升级时找到它
    • 如果将包含文件中的代码复制到 %report1 和 %report2 中,则似乎没有范围问题,因为两者都有效。范围似乎只有在使用 %inc 时才会成为一个问题,我认为,以真正的技术方式,我们想知道为什么,因为我们无法弄清楚!
    • 马克,我更新了答案。 SAS 中的一些宏观内容很可怕,我个人已经放弃尝试完全理解所有内容:)
    猜你喜欢
    • 2020-02-20
    • 1970-01-01
    • 2020-02-01
    • 2017-05-19
    • 1970-01-01
    • 1970-01-01
    • 2014-12-04
    • 2014-05-12
    • 2014-04-18
    相关资源
    最近更新 更多