为什么 proc 在 SAS 宏中编写时不需要 % 符号
Why proc does not need a % symbol when written inside a SAS macro
我有一个关于 SAS 宏的基本问题。在 sas 宏中,当你写一个 let 语句或一个 put 语句或一个 if 语句时,你总是在它前面加上 %.
但是当你在宏里面写一个'proc'的时候,为什么我们不需要写%proc呢?
或者例如 %data?
%
表示宏语法——宏函数、宏语句或宏命令。基本上,SAS Macro Language Reference 涵盖的内容。
当你在宏中有一个过程时,你要求宏做的就是将该过程键入堆栈,就像你已经键入它一样。您不需要 %
因为 proc 是您要求输入的文本,而不是对宏语言解释器本身的命令。
SAS Macro language和SAS Base是两种本质上独立的语言——后者是SAS的核心,前者是一个帮手,可以让某些重复性的事情变得更容易。它们只是松散地集成。
%let
或 %put
是宏语句:它们与您可以在数据步骤中使用的 put
不同。它们共享名称和功能的基本概念,但除了 c and printf
in r 中的 printf
没有其他共同点。
因为数据步语言和宏语言是两种不同的编程环境。当 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;
当我们 运行 宏 2 时,我们将得到完全相同的输出,但它的执行方式不同。
当我们编译宏foo2
时,我们还存储了一些关于内部宏循环的信息。这个特定的循环只是按顺序创建文本 "var1 var2 var3"。请注意,在循环之前有一段文字:"keep." 这是完全有效的,因为它只是一段文字。
我们在数据步骤中执行宏。当我们开始数据步骤的编译过程时,单词扫描器找到宏触发器 %
并将该信息传递给宏处理器。当它发现 foo2
是一个有效的已编译宏时,宏处理器 运行 执行宏程序,并将生成的文本发送到单词扫描器:
keep
var1
var2
var3
我们故意用分号结束宏的调用。这告诉词扫描器我们在语句的末尾,最终被发送到编译器。
一旦宏完成,单词扫描仪就会继续前进,将语句传递到输入堆栈,直到它到达 run
边界或另一个 proc
步骤。
我们可以在数据步骤之外调用 foo2
,但 SAS 会出错并指出它们不是有效语句。这相当于在一行中键入 keep var1 var2 var3;
并尝试 运行 它。那段特定的文本仅在数据步骤中有用,尽管 SAS 会很乐意 运行 它随处可见。
SAS 看不到宏。它只理解数据步骤和过程语言。只有宏处理器才能看到和使用宏触发器。单词扫描器阻止编译器看到任何宏触发器。将单词扫描器想象成一个特殊的过滤器:它只将文本分发到可以读取它的地方。
有一些例外,数据步骤中的一些函数可以弥合 SAS 和宏之间的差距,但实际上与此没有任何关系。
出于同样的原因,我在编辑 HTML 时不必在网页中的单词周围键入 <>
。我网页中的文字不是 HTML 命令,就像 SAS 代码语句不是 SAS 宏处理器的命令一样。
我有一个关于 SAS 宏的基本问题。在 sas 宏中,当你写一个 let 语句或一个 put 语句或一个 if 语句时,你总是在它前面加上 %.
但是当你在宏里面写一个'proc'的时候,为什么我们不需要写%proc呢? 或者例如 %data?
%
表示宏语法——宏函数、宏语句或宏命令。基本上,SAS Macro Language Reference 涵盖的内容。
当你在宏中有一个过程时,你要求宏做的就是将该过程键入堆栈,就像你已经键入它一样。您不需要 %
因为 proc 是您要求输入的文本,而不是对宏语言解释器本身的命令。
SAS Macro language和SAS Base是两种本质上独立的语言——后者是SAS的核心,前者是一个帮手,可以让某些重复性的事情变得更容易。它们只是松散地集成。
%let
或 %put
是宏语句:它们与您可以在数据步骤中使用的 put
不同。它们共享名称和功能的基本概念,但除了 c and printf
in r 中的 printf
没有其他共同点。
因为数据步语言和宏语言是两种不同的编程环境。当 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;
当我们 运行 宏 2 时,我们将得到完全相同的输出,但它的执行方式不同。
当我们编译宏foo2
时,我们还存储了一些关于内部宏循环的信息。这个特定的循环只是按顺序创建文本 "var1 var2 var3"。请注意,在循环之前有一段文字:"keep." 这是完全有效的,因为它只是一段文字。
我们在数据步骤中执行宏。当我们开始数据步骤的编译过程时,单词扫描器找到宏触发器 %
并将该信息传递给宏处理器。当它发现 foo2
是一个有效的已编译宏时,宏处理器 运行 执行宏程序,并将生成的文本发送到单词扫描器:
keep
var1
var2
var3
我们故意用分号结束宏的调用。这告诉词扫描器我们在语句的末尾,最终被发送到编译器。
一旦宏完成,单词扫描仪就会继续前进,将语句传递到输入堆栈,直到它到达 run
边界或另一个 proc
步骤。
我们可以在数据步骤之外调用 foo2
,但 SAS 会出错并指出它们不是有效语句。这相当于在一行中键入 keep var1 var2 var3;
并尝试 运行 它。那段特定的文本仅在数据步骤中有用,尽管 SAS 会很乐意 运行 它随处可见。
SAS 看不到宏。它只理解数据步骤和过程语言。只有宏处理器才能看到和使用宏触发器。单词扫描器阻止编译器看到任何宏触发器。将单词扫描器想象成一个特殊的过滤器:它只将文本分发到可以读取它的地方。
有一些例外,数据步骤中的一些函数可以弥合 SAS 和宏之间的差距,但实际上与此没有任何关系。
出于同样的原因,我在编辑 HTML 时不必在网页中的单词周围键入 <>
。我网页中的文字不是 HTML 命令,就像 SAS 代码语句不是 SAS 宏处理器的命令一样。