加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

CALL EXECUTE的用法

(2014-07-03 22:11:23)
标签:

sas

callexecute

分类: SAS笔记

对call execute的用法描述:解析其包含的语句,并且在下一个过程步或者data步中运行(如果解析值是一个SAS语句)或者立即运行(如果解析值是一个宏语句)。

 

很多情况下,CALL EXECUTE()可以实现宏的效果。使用宏,我们需要“定义宏”+“调用宏”;使用CALL EXECUTE(),我们可以在DATA步的执行过程中,根据变量的值生成不同的代码,而这些代码会在DATA步执行完后自动运行。

比如,下面的例子可以求出数据集中数值型变量的描述性统计和字符型变量各个值的频数:

data _null_;
    set sashelp.vcolumn;
        where libname="SASHELP" and memname="CLASS";

        *** Get Frequency table for character var;
        if type="char" then
                       call execute("proc freq data=sashelp.class;
                                        table "||strip(name)||"/out=freq_"||strip(name)||";
                                     run;"
                                           );

        *** Get descriptive statistics for numeric var;
        else if type="num" then
                     call execute("proc means data=sashelp.class;
                                        var "||strip(name)||";
                                         output out=stat_"||strip(name)||";
                                     run;"
                                        );
run;

如果CALL EXECUTE()的参数值只包含SAS语句的话,理解起来是比较简单和直观的。但如果其参数值包含宏的因素(宏变量,宏语句,宏的调用)时,理解起来就可能比较困难,难点就在于究竟宏变量的值是什么时候解析的,以及宏语句是什么时候被执行的。

CALL EXECUTE() 中的宏变量

下面这个例子可以用来说明CALL EXECUTE()中宏变量的解析情况:

%macro test(aa);
     data test;
             x='&aa';
             y=symget('aa');
                 put x= y=;
         run;
%mend;

%let aa=Good;

data _null_;
    *** Double quotation;
    call execute("%test(bad)");

    *** Single quotation;
    call execute('%test(bad)');
run;

程序解释:

数据集TEST中变量X的值:

第一个CALL EXECUTE()所产生的数据集中 X的值为’bad’。这是因为当宏的调用放到双引号中时,宏的执行是在DATA步的编译阶段进行的。而宏执行的结果(’data test’ 代码)再放到一对双引号之间作为CALL EXECUTE() 的参数。这就相当于:

call execute("data test; x='&aa'; y=symget('aa'); put x= y=; run;");
 这时虽然宏变量aa的引用用两边是单引号(’&aa’),但是整个字符串却处在双引号里面,因而单引号会被当成普通字符,并不会影响到&aa的解析为宏参数的值--bad。这样DATA步编译完后,第一个CALL EXECUTE() 就会是:

call execute("data test; x='bad'; y=symget('aa'); put x= y=; run;");
 第二个CALL EXECUTE()所产生的数据集X的值为'&aa'。这是因为宏的调用位于单引号中,所以DATA步编译阶段宏不会执行。而在DATA步的执行阶段,CALL EXECUTE() 中调用的宏会被执行,产生的SAS代码会去排队(在input stack中)等待运行。这时&aa两边的单引号就会发挥其“屏蔽宏变量解析”的功能,因此X的值即为'&aa'.

数据集TEST中变量Y的值:'Good'

因为SYMGET()函数的参数只是宏变量的名字'aa'而不用符号’&’,因此在DATA _NULL_步的编译和执行过程中都不会试图去解析宏变量aa的值。而等DATA _NULL_执行完毕,CALL EXECUTE()所产生的代码执行时,SYMGET()才去尝试找aa的值。需要注意的是,此时的代码并不在宏的执行环境里,而是在open code。所以SYMGET() 返回的aa的值不是%test宏的参数值,而是global symbol table中的值—Good

另外,如果希望SYMGET()函数返回宏%test所指定的参数值,可以用: 

call execute('%nrstr(%test(bad))');

a. 单引号的使用可以跳过所在DATA步的编译阶段;

b. %NRSTR()的使用可以使宏的执行跳过所在DATA步的执行阶段;

这就相当于DATA步执行完毕后直接调用宏:%test(bad)

如果CALL EXECUTR()的参数中有宏语句,那么宏语句在何时执行会有三种情况:

1.如果宏语句在双引号中并没有使用%NRSTR(),宏语句会在DATA步编译阶段执行;
2.如果宏语句在单引号中,或者在双引号中并使用了%NRSTR(),宏语句会在DATA步执行阶段执行;
3.如果宏语句在单引号中,并且使用了%NRSTR(),则宏语句会在DATA步执行完之后执行。

对下面这个例子也可以同样解释:

data prices; 
   input code amount;
   datalines;
56 300
99 10000
24 225
;
%macro items;
   %global special;
   %let special=football;
%mend items;
data sales;   
   set prices;
   length saleitem $ 20;
   call execute('%items');
   saleitem="&special";

   put saleitem;
run;

结果在log中显示为

&special

&special

&special

但是如果将代码中的call execute('%items');改成call execute("%items");则可以得到另外一个结果:

football

football

football

从这个例子中可以看出单引号和双引号的区别所在。

原文转自人大经济论坛http://bbs.pinggu.org/thread-2377205-1-1.html

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有