1、
call execute的意思就是“执行这段代码”,但是一个data步中间的call execute是不可能直接执行的,只有data步结束了这段代码才能执行。
2、
if ... then do; proc ... ; end;这样是无法执行的
if ... then call execute('...');else call execute('...') 这样是可以执行的
%if %then %do;这样的语句只能在宏语言中有效
if ... then call execute('...');这样的效果是一样的
3、
将多个call execute结合起来,可以根据数据集里面的数据产生一个更加复杂的过程步
eg.
根据一个数据集里的数据来对另一个数据集进行分类
obs sat_cutoff group_name
1 1200 Honor students
2 900 Regular track
3 300 Challenged
分类信息
- data _null_;
- set cutoffs end=lastone;
- if _n_=1 then call execute("data student_groups;
- set all_students;
- length group $ 14;");
- call execute("if score>="||put(sat_cutoff,best16.));
- call execute("then group='"||group_name||"';");
- if lastone=0 then call execute("else");
- else call execute("run;");
- run;
- data student_groups;
- set all_students;
- length group $14;
- if score>=1200 then group='Honor students';
- else if score>=900 then group='Regular track';
- else if score>=300 then group='Challenged';
4、call execute 中的过程步最好是能够用run来结尾;
call execute里面的宏是会立即执行的
eg.
call execute('%let pet=DOG;');
animal = symget('pet');
put animal; ->DOG
%let pet=CAT;
data _null_;
if 5>4 then do;
%let pet=DOG;
end;
if 5=4 then do;
%let pet=RAT;
end;
animal = symget('pet');
put animal; -> RAT
run;
所有的%let都会执行
%let pet=CAT;
data _null_;
if 5>4 then do;
call execute ('%let pet=DOG;');
end;
if 5=4 then do;
call execute ('%let pet=RAT;');
end;
animal = symget('pet');
put animal; -> DOG
run;
有趣的小例子
- %macro mymac;
- %let color=blue;
- %put Color began as &color...;
- data _null_;
- call symput('color','red');
- run;
- %put Color ends up as &color...;
- %mend mymac;
- %mymac
Color ends up as red.
- data _null_;
- call execute('%mymac');
- run;
Color ends up as blue.
因为宏会立即执行,而data步会在这个data步结束了才执行。
5、如何延迟call execute的执行,使过程步可以推迟执行
有时候我们不希望宏会马上执行,而是希望能够在data步之后再执行。
%let value = BEFORE;
data _null_;
call execute("data _null_; call execute ('%"||"let value = AFTER;');run;" );
data_step_var=symget('value');
put data_step_var; -> BEFORE
run;
%put Value is &value ..; ->Value is AFTER.
单独的将%let分开 或者用一个call execute 嵌套是不能使这个宏推迟执行的,只能在使用嵌套的同时将%let分开才可以。
另一个方法:
%let value=BEFORE;
data _null_;
call execute('%nrstr(%let value=AFTER;)');
data_step_var = symget('value');
put data_step_var; ->BEFORE
run;
%put Value is &value..; ->Value is AFTER.
6、宏变量的解析
单引号是会阻止宏变量的解析的。call symput和call execute的组合会因为单引号和双引号而产生不同的结果:
- %let value = BEFORE;
- data _null_;
- call symput('value','AFTER');
- call execute("%put Double Quotes: value is &value...;");
- call execute('%put Single Quotes: value is &value...;');
- run;
单引号的结果为 value is AFTER;