打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
SAS岩论 | Macro系列(3)——运行机制

Macro系列导读

谷子歌按

我碰到过很多SAS初学者,采用“拿来主义”的态度,调用别人写的SAS macro,或者修改别人的SAS macro,开发自己的SAS macro时,总是碰到俩类问题:这样的问题和那样的问题。而且很多初学者面对错误时,经常不知道错误的缘由,甚至坚信自己肯定没错,一定是SAS出问题了。究其原因,还是基础不够扎实,如果能够耐下心来,对SAS macro运行机制多做一些了解,情况也许会好很多。本节内容,推荐程度:※※※※※

SAS Macro作为SAS高手不可或缺的一项技能,是因为它功能足够强大,能极大的提升程序开发效率;使你的时间和精力投入在更有价值的事情上。

Macro系列文章,将会逐一奉上SAS Macro的点点滴滴,带你踏上从认识Macro到熟练使用Macro之路。掌握SAS Macro,将会使你的SAS编程能力更上一层楼。

上期文章“Macro总述篇”对Macro的主要用途进行了说明,进而对其构成组成进行了介绍,主要包括Macro Variables和Macro Programs。其本质都是做文本替换,Macro Variables为简单直接的替换,而Macro Programs则可以实现复杂、灵活的替换。

Macro系列(3)——运行机制

本期文章主要针对Macro的运行机制进行介绍,抛开表现看本质,搞清楚Macro Language与SAS Language之间有什么联系,又有什么区别。当你提交程序的时候,它俩到底是怎么执行的。

SAS程序运行过程

首先来了解下当我们提交运行一个DATA步程序后,具体发生了什么事情。

SAS程序与其他程序一样,在运行时都要经过两个阶段:编译(Compilation)、执行(Execution)。

  1. 程序首先经过编译阶段,该阶段主要检查代码语法错误,以及执行一些编译时语句及创建PDV,缓存等相关的环境。如果发现代码存在语法错误,则不进入执行阶段,并且将发现的所有语法错误问题在日志中显示;

  2. 如果在编译阶段未发现语法错误,则程序会进入执行阶段,真正运行代码,读取数据,处理数据。

具体的过程,如下所示:

小贴士

SAS程序中的语句,按照其在编译阶段还是执行阶段生效,可分为三种:

  • 仅在编译阶段有效,例如:length、format、label、retain、keep、drop等语句,一般是有关变量属性的语句;

  • 仅在执行阶段有效,例如:if-else、do while等条件控制及循环语句;

  • 在编译和执行阶段都有效,例如:set、merge等语句,在编译阶段会读取数据的元数据信息,在执行阶段开始读取数据。

进一步深入

在熟悉了上面程序运行时的两个阶段之后,对了解Macro的运行机制还是不够的,需要进一步深入。

其实SAS程序在编译之前还有一个更细节的步骤,称之为“Tokenization”;这个过程类似于文本挖掘当中的分词过程。该过程将整段程序分块,然后逐一读取。完成这项工作的组件称之为“Word Scanner”,该组件将程序拆分成一个个的小块,称之为“Token”。

所以,Token就类似于分词过程中词典中的词,它有以下4种形式:

  • Literal:用引号引起来的字符串

  • Number:包括:纯数字、日期常量、时间常量、十六进制数

  • Name:以字母或者下划线开头的字符串

  • Special:其他的一些符号,例如:* / + - ** ; $ ( ) . & % =

在完成Tokenization的过程时,涉及到一个区域叫“Input Stack”。它就是在内存中的一块区域。用于临时保存提交的代码。所以,更深入一些来看,当你提交SAS程序后有以下4个过程:

  1. 将提交的代码Copy到Input Stack

  2. Word Scanner完成Tokenization的工作,启动编译器,发送Tokens到Compiler;

  3. Compiler接收Word Scanner发送的Tokens。如果所有的Tokens都接收完毕,或者遇到一个DATA Step boundary,开始Compiling;

  4. 程序编译完无错误,开始Executing

小贴士

Compiler每遇到一个DATA STEP Boundary,就停止接收Tokens。开始编译当前的程序,并且执行;等当前的程序执行完毕后,重新开始接收Tokens,直到遇到下一个DATA Step Boundary,编译执行;依次循环运行。

如果想更加直观一点感受Tokenization是如何进行的,请看下图(这个图做起来真心不容易):

为什么要有这么一个Tokenization的过程,如果你想不通,请继续往下看。

备注

至于Word Scanner是一个个Token发送,还是多个Tokens发送,不必细究;只需要清楚有这么一个过程就好了。此处为了方便演示,是以一个Statement为单位进行发送。

Macro来了

理解了上文所讲的过程,我们再来看,程序中有Macro Language的时候又是怎么处理的。在本系列第1篇——入门篇文章中有提到,Macro Language与SAS Language可以看做是独立的,而且Macro Language是由专门的Macro Processor来处理的(批注1)

因此,为了与SAS Language进行区分,Macro Language有特殊符号标记。

具体到Macro Variables和Macro Programs来说:

  • 要使用Macro Variables,要在其名字前加“&”。例如“&age”,表示使用age这个Macro Variable;

  • 要写Macro Programs,所有相关的语句、函数等都需要加“%”。例如“%IF”,表示是Macro中的IF语句。

所以说,当程序中有“&”或者“%”出现的地方(除掉它们作为纯字符的情况),就代表此处是Macro Language。因此,“&”和“%”被称之为Macro Trigger,在Tokenization的阶段,如果遇到这两个符号之一,将会启动Macro Processor去处理。

下面再通过一个GIF让你明白Macro究竟是怎么处理的。现假设已经定义了一个宏变量“age_value”,其值为14。使用该Macro Variable从sashelp.class数据集中筛选出age大于14的数据,来看内部是如何运行的。请看下图:

我们可以看到,在Word Scanner遇到Macro Trigger的时候,便会启动Macro Process;此时会暂时停止Scanning,等待Macro Processor处理。等Macro Process处理完毕之后,继续Scanning,发送Token到Compiler。当然,Macro Trigger是不会被发送到Compiler中。

在此处,是简单的使用了Macro Variable,Macro Processor将其替换为其取值。如果是Macro Program的调用,也是一样,将其替换为该Macro Program包含的内容。

看到这里,你应该会明白为什么会有Tokenization这么一个过程;而且,你也应该会明白,为什么Macro是在SAS Language编译前就处理完毕了;进而,你就会想明白,它是如何协助你写程序的。

A program that writes program.

所以,需要永远记住:Macro是帮你写SAS程序的,是在SAS Language编译之前就处理完了。记这一点,将会使你学习Macro的道路插上翅膀。

(此处说Macro在SAS Language编译之前就处理完毕,指的是正常情况下的直接引用或者调用;比较特殊的高级用法,后面的文章会一一介绍)。

这期的内容到这就结束了,相信通过这三期的文章,不了解Macro的也会对Macro有一个比较深入的认识;了解Macro的对Macro的理解或许更加深入了一些,以前有些想不明白的问题可能突然之间就明白了。

下期文章开始,将会正式步入Macro的内容介绍,首先是“Macro Variables”。更多内容,请持续关注SAS中文论坛——“SAS岩论 | Macro系列”。

 

作者:辛岩,从事了多年的SAS数据分析挖掘工作,担任过项目经理、技术顾问、培训讲师等职务,拥有丰富的项目实战经验。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
原创 新手必看 SAS入门 (不断更新中)
C?变量和函数开头加一个和两个下划线的作用
JVM远程调试为什么要禁用JIT
java回顾(1)------Java语言的运行机制
Java教程:Java的运行机制是什么
分享了解java的运行机制是什么
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服