在SAS中,执行没有分号的宏?

时间:2014-10-21 15:51:42

标签: sas sas-macro

我在SAS中多次运行宏,如下所示:

%mymac(a,b);
%mymac(a,c);
.
%mymac(a,a)
%mymac(a,w);
.

我的程序/宏类似于:

/* begin program here */

data original_data;
set mylib.mydata;
run;

%macro mymac(x,y);

data mydata1;
set original_data;
where school_district="&x";
run;

proc means data=mydata1;
var income;
run;

%mend mymac;

我意识到我忘记了分号(如(a,a)中的分号)并且SAS似乎并不介意。它运行所有的宏调用没有问题。当我添加分号时,我比较了输出,我看不出有什么区别。

这是正常的,SAS没有给出缺少分号的错误吗?

3 个答案:

答案 0 :(得分:4)

宏调用需要 分号。

通常它们被包括在内,因为人们习惯于将分号视为“终止声明”或结束行的方式。我个人更愿意尽可能包含它们,因为我相信它使我的代码更具可读性。

请记住,宏只是评估自己并返回它们解决的任何内容,这可能是一个看起来像数字,字符串或其他任何内容的代码块......

以没有使用分号的示例为例:

%macro field_list();
    name, 
    age, 
    sex, 
    height
%mend;

proc sql;
  select %field_list()
  from sashelp.class
  ;
quit;

尝试在启用了option mprint;的计算机上运行它。运行宏的结果只返回其中的代码块。这导致执行以下代码:

proc sql;
  select  name, age, sex, height
  from sashelp.class
  ;
quit;

如果在调用我们的宏之后我们有一个分号,那么SAS尝试运行的代码将包含分号,这将是无效的语法,如下所示(注意高度后的分号):

proc sql;
  select  name, age, sex, height ;
  from sashelp.class
  ;
quit;

这是因为调用宏不需要分号,因此它只会被遗忘并包含在执行步骤中。

当您在上面给出的示例中调用宏时,可以包含分号,因为您的宏是完全自包含的步骤。在开放代码中,如下所示有无关的分号是没有害处的:

%macro example2(inDS=, outDs=);
  data &outDs;
    set &inDs;
  run;
%mend;

%example2(inDS=sashelp.class, outDs=tmp_class);

这基本上评估为:

data tmp_class;
  set sashelp.class;
run;;

请注意我们通话结尾留下的额外分号?我们可以拥有我们想要的尽可能多的代码仍然可以正常运行,即:

%example2(inDS=sashelp.class, outDs=tmp_class);;;;;;

解析为:

data tmp_class;
  set sashelp.class;
run;;;;;;;

由于它是有效的语法,因此仍可正常运行。

答案 1 :(得分:3)

通常很好。关于SAS Macro的主要理解是它是一个代码生成工具,而不是真正的编程语言。虽然%my_mac(x,y);看起来像是一种类似C语言的传统函数调用,但您希望以;结束每个语句,此处终止;没有实际意义。相反,它是在%my_mac(x,y)内部生成的SAS代码。在您的情况下,该代码是语法SAS,并且很好。如果您在心理上将%my_mac(x,y)来电替换为其生成的代码(即data mydata.....run;),即使没有%my_mac(x,y) ;,也会看到它是语法上的。如果您改为编写%my_mac(x,y);,它只会生成data mydate.....run;;,这很好,但;是多余的。

事实上,跳过分号也是一个拥有宏的返回值的黑客。例如:

%MACRO x_plus_n (x = , y= );
    %SYSEVALF (&x + &y)
%MEND;

%LET x = 3 ;
%LET y = 4 ;
%LET z = %x_plus_n (x = &x , y= &y) is the result;
%PUT ------------- &z;

注意%SYSEVALF行上缺少;。这允许宏在%LET z = ....开始的行结束之前不会终止,其中有;x_plus_n创建的输出成为宏的一种返回值。

答案 2 :(得分:2)

宏只是文本替换。它们本身通常不是可执行语句(尽管它们有时可以使用%SYSFUNC执行语句)。因此,在宏调用之后不需要分号,除非在宏中包含的文本之后需要分号(并且实际上不包含在宏本身中)。

IE:

%macro test;
proc freq data=sashelp.class;
run
%mend test;

必须以

执行
%test;

因为run没有终端分号。如果你在宏run之后放了一个分号,那么你可以在没有分号的情况下将其作为%test运行。

记住第一句话:宏只是文本替换。无论宏生成什么文本,都会进入SAS程序并执行,就好像你输入它一样(也许你使用%do i=1 %to 100; - 所以它会放置100个循环内容的副本 - 但就好像你你自己打了100个)。因此,对;的需求取决于您是否需要输入它。