为什么proc在SAS宏中写入时不需要%符号

时间:2015-11-13 20:54:56

标签: sas sas-macro

我有一个关于SAS宏的基本问题。在sas宏内部,当你编写一个let语句或put语句或if语句时,你总是用%前缀。

但是当你在宏中写一个'proc'时,为什么我们不需要写%proc? 或者例如%data?

3 个答案:

答案 0 :(得分:5)

因为数据步骤语言和宏语言是两种不同的编程环境。当SAS对您的语句进行标记时,它会查找特定的关键字。其中一个关键字是%触发器。在运行任何内容之前,扫描程序一词将SAS语句中的宏语句分离出来并将它们传递给适当的处理器。在SAS语句之前总是编译和解析宏语句。

当您使用宏时,您将文本字符串存储在某个宏变量或宏程序中。就SAS而言,宏变量或程序内部的任何内容都是原始文本。

考虑以下两个宏:

宏1:

%macro foo1;
    data bar1;
       var1 = 'a';
       var2 = 'b';
       var3 = 'c';
       var4 = 'd';

       keep var1-var3;
    run;
%mend;

宏2:

%macro foo2;
       keep
       %do i = 1 %to 3;
           var&i
       %end;
%mend;

data bar2;
   var1 = 'a';
   var2 = 'b';
   var3 = 'c';
   var4 = 'd';

   %foo2;
run;

编译宏1时,在调用它之前没有任何反应。这是因为您已将所有文本存储在宏程序中。当你调用宏语句时:

%foo1;

SAS将短语foo1传递给宏处理器,程序运行,解析后的文本再次回到单词扫描程序中,然后逐个处理单个标记。就SAS而言,它完全可以看到内部包含的datastep:

data bar1;
   var1 = 'a';
   var2 = 'b';
   var3 = 'c';
   var4 = 'd';

   keep var1-var3;
run;

当我们运行Macro 2时,我们将获得完全相同的输出,但它的执行方式不同。

当我们编译宏foo2时,我们还存储了一些关于内部宏循环的信息。此特定循环只是顺序创建文本“var1 var2 var3”。请注意,循环之前有一段文字:“keep。”这完全有效,因为它只是一段文字。

我们在数据步骤中执行宏。当我们开始数据步骤的编译过程时,单词scanner扫描程序找到宏触发器%并将该信息传递给宏处理器。当它发现foo2是一个有效的编译宏时,宏处理器运行宏程序,并将生成的文本发送到单词scanner:

keep
var1
var2
var3

我们故意以分号结束宏的调用。这告诉扫描器这个词我们在一个语句的末尾,最终会被发送到编译器。

宏完成之后,扫描程序一直保持不变,将语句传递给输入堆栈,直到它到达run边界或其他proc步骤。

我们可以在数据步骤之外调用foo2,但SAS会错误地说它们不是有效的语句。这相当于在一行上键入keep var1 var2 var3;并尝试运行它。该特定文本仅在数据步骤中有用,尽管SAS很乐意尝试在任何地方运行它。

SAS没有看到宏。它只能理解数据步骤和proc语言。只有宏处理器才能看到并使用宏触发器。单词scanner扫描程序可防止编译器看到任何宏触发器。将扫描仪这个词想象成一个特殊的过滤器:它只将文本分发给可以读取它的地方。

有一些例外情况,数据步骤中的某些功能可以弥合SAS和宏之间的差距,但它实际上并没有与此有任何关系。

答案 1 :(得分:2)

%表示宏语法 - 宏函数,宏语句或宏命令。基本上,SAS Macro Language Reference涵盖的内容。

当您在宏中有一个proc时,您要求宏执行的操作就是将该proc键入堆栈,就像您键入它一样。您不需要%,因为proc是您要求输入的文本,而不是宏语言解释器本身的命令。

SAS宏语言和SAS Base是两种基本上不同的语言 - 后者是SAS的核心,前者是一种帮助,可以更容易地做某些重复的事情。它们只是松散地整合在一起。

%let%put是宏语句:它们与您在数据步骤中可以使用的put不同。他们分享了功能的名称和基本概念,但printf printf中的Function共同拥有其他内容。

答案 2 :(得分:0)

出于同样的原因,当我编辑HTML时,我不必在网页中的字词周围输入<>。我的网页中的单词不是HTML命令,就像SAS代码语句不是SAS宏处理器的命令一样。