在SAS中,执行不带分号的宏?
我在SAS中多次运行宏,如下所示:在SAS中,执行不带分号的宏?,sas,sas-macro,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
%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不给出缺少分号的错误是正常的吗?通常可以。了解SAS宏的主要内容是它是一种代码生成工具,而不是一种真正的编程语言。而
%my_mac(x,y)
看起来像是C语言中的传统函数调用,在这里,您希望用结束每个语句代码>,这里是一个终止代码>没有实际意义。相反,它是在%my_mac(x,y)
内部生成的SAS代码。在您的情况下,该代码符合语法要求,可以使用。如果您在心里用它生成的代码替换%my_-mac(x,y)
调用(即data mydata…..run;
),您会发现即使在%my_-mac(x,y)
结尾处使用,它也是合乎语法的代码>。如果你写了%my_mac(x,y)相反,它只会生成数据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\u plus\n
创建的输出成为宏的一种返回值。宏只是文本替换。它们本身通常不是可执行语句(尽管它们有时可以使用%SYSFUNC
执行语句)。因此,在宏调用之后不需要分号,除非在宏中包含的文本之后需要分号(实际上并不包含在宏本身中)
即:
必须按规定执行
%test;
因为运行
没有终端分号。如果在宏中的run
后面加上分号,则可以将其作为%test
运行,而不使用分号
记住上面的第一句话:宏只是文本替换。宏生成的任何文本都会被塞进SAS程序,并像您键入它一样执行(可能您使用了%do i=1%到100;
-因此它会将循环中所有内容的100个副本放入循环中-但就好像您自己键入了所有100个)。因此需要一个代码>取决于您是否需要键入它。宏调用不需要分号
通常,分号包括在内,因为人们习惯于将分号视为“终止语句”或结束行的一种方式。我个人更喜欢在可能的情况下包含它们,因为我相信这会使我的代码更具可读性
请记住,宏只需对自身进行求值,并返回它们解析的任何内容,这些内容可能是看起来像数字、字符串或其他任何内容的代码块
以不使用分号的示例为例:
%macro field_list();
name,
age,
sex,
height
%mend;
proc sql;
select %field_list()
from sashelp.class
;
quit;
尝试在自己的机器上使用选项mprint运行它代码>已启用。运行宏的结果只是返回其中的代码块。这将导致执行以下代码:
proc sql;
select name, age, sex, height
from sashelp.class
;
quit;
如果在调用宏之后有一个分号,那么SAS将尝试运行的代码将包括分号,这将是无效的语法,如下所示(请注意高度后的分号):
这是因为调用宏时不需要分号,所以它只会被留下并包含在步骤的执行中
当您像在上面给出的示例中那样调用宏时,可以使用分号,因为宏是一个完全自包含的步骤。在开放代码中,使用这样的分号没有什么害处:
%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;;;;;;;
它仍然可以正常运行,因为它是有效的语法。基本上,每次调用mydata1数据集时,我的宏都会创建mydata1数据集。我不是最擅长使用宏的,也不确定我是否完全理解您的示例。@sparc_spread-我通过在宏调用和分号之间添加文本使示例更有意义。如果没有额外的文本,您试图表达的观点就不那么明显了。如果没有编辑,这基本上与问题的要求相反(宏中缺少了有用的;
,而不是原始问题所做的,在宏之外跳过)。“这样的编辑是恰当的。”乔同意了。我编辑了一段新的开头段落,更直接地解决了这个问题,“返回值黑客”现在是一个有用的事后思考。因此,如果我完全正确地理解了这一点,我不需要在上述宏的末尾使用分号,因为最后一条语句中有一个分号,所以在%mymac(a,a)中添加一个分号基本上与输入run相同;;在资产负债表的末尾?是的,这是完全正确的。
%example2(inDS=sashelp.class, outDs=tmp_class);;;;;;
data tmp_class;
set sashelp.class;
run;;;;;;;