宏类似于c中的函数,传入指定参数后执行,并且宏内部可以包含data步程序和条件运算符号。
宏变量只是小小的变量、、、、(by the way作用也很大)
1:宏的基本语法
如何创建一个简单的宏并使用?
%macro prtlast; proc print data=&syslast (obs=5); title "Listing of &syslast data set"; run; %mend; %prtlast /*不要加分号,加了有可能出错*/
宏创建过程中做了什么工作?
1:提交程序后会传递给word scanner,扫描分解为tokens,然后再传给宏处理器
2:检查所有宏语法,其他的不是宏的部分在执行时再检查(比如上面的程序,即使proc写成pro c在宏创建时也不会报错,他只会检查&%这些地方或者条件语句中的%do等部分)
3:如果有错误,则创建dummy (non-executable) macro
4:如果无错误则会保存在work.sasmacr目录下,并命名为macro-name.macro
哪些关键字不能给宏命名?
ABORT ACT ACTIVATE
BQUOTE BY
CLEAR CLOSE CMS COMANDR COPY
DEACT DEL DELETE DISPLAY DMIDSPLY DMISPLIT DO
EDIT ELSE EVAL
FILE
GLOBAL GO GOTO
IF INC INCLUDE INDEX INFILE INPUT
KEYDEF
LENGTH LET LIST LISTM LOCAL
MACRO METASYM
NRBQUOTE NRQUOTE NRSTR
ON OPEN
PAUSE PUT
QSCAN QSUBSTR QSYSFUNC QUOTE QUPCASE
RESOLVE RETURN RUN
SAVE SCAN STR SUBSTR SUPERQ SYSCALL SYSEVALF SYSEXEC SYSFUNC SYSGET SYSRPUT
THEN TO TSO
UNQUOTE UNSTR UNTIL UPCASE
WHILE WINDOW
如何查看宏是否创建成功?(调试宏选项)
mcompilenote=none/noautocall/all
none不会在日志中输出信息
noautocall会在日志中输出非autocall macros的所有宏的信息
all输出所有信息
1 options mcompilenote=all; 2 %macro mymacro; 3 %mend mymacro; NOTE: The macro MYMACRO completed compilation without errors.
宏是如何被运行的?
1. searches the designated SAS catalog (Work.Sasmacr by default) for an entry named Macro-name.Macro.
2. executes compiled macro language statements within Macro-name.(执行被编译好的宏的部分)
3. sends any remaining text in Macro-name to the input stack for word scanning.(执行其余的文本部分,比如上面的print过程)
4. suspends macro execution when the SAS compiler receives a global SAS statement or when it encounters a SAS step boundary.
5. resumes execution of macro language statements after the SAS code executes.
宏运行过程可以和两部分打交道,第一部分为符号表,第二部分为input stack
2:调试宏
2.1:当调用宏时,宏中不是宏语言的部分不会在log中显示,可以用如下选项将其显示
options mprint/nomprint
the text that is sent to the SAS compiler as a result of macro execution is printed in the SAS log
23 options mprint; 24 %prtlast MPRINT(PRTLAST): proc print data=WORK.SALES (obs=5); MPRINT(PRTLAST): run;
2.2:prints messages that indicate macro actions that were taken during macro execution.
OPTIONS MLOGIC | NOMLOGIC;
provide feedback in the log about the parameter values passed into this macro when invoked
看看啥叫feedback!!!注意后三行
MLOGIC(MAKEPGM): 准备开始执行。 MLOGIC(MAKEPGM): 参数 NEWNAME 的值为 res MLOGIC(MAKEPGM): 参数 SETNAME 的值为 sashelp.class MLOGIC(MAKEPGM): 参数 PRINT 的值为 YES
/*红色字体为作用效果*/options nomprint mlogic; 107 %prtlast MLOGIC(PRTLAST): Beginning execution. NOTE: There were 1 observations read from the dataset WORK.SALES. NOTE: PROCEDURE PRINT used: real time 0.02 seconds cpu time 0.02 seconds MLOGIC(PRTLAST): Ending execution.
2.3:log中打印内部宏的步骤,打印内部宏的逻辑
OPTIONS MPRINTNEST | NOMPRINTNEST;
OPTIONS MLOGICNEST | NOMLOGICNEST;
2.4:SOURCE2 writes source statements that are inserted by %INCLUDE statements
3:创建带参数的宏
3.1:Macros That Include Positional Parameters
3.2:Macros That Include Keyword Parameters
Keyword parameters can be listed in any order. Whatever value you assign to each parameter (or variable) in the %MACRO statement becomes its default value. Null values are allowed.
When you call a macro whose definition includes keyword parameters, you specify both the keyword and the value for each parameter, in any order. If you omit a keyword parameter from the macro call, the keyword variable retains its default value,引用时一定要列出keyword和value,如果不列出则表示使用默认值
关键字参数可以摆放在任意位置,赋值的话即为默认值,默认值可以为null
其实这里的形式和c++中函数的默认参数十分类似,赋值为默认的话调用时省略不写即为调用默认
使用方式
%macro-name(keyword-1=value-1<,...,keyword-n=value-n>)
将course_code course_title days赋值给vars%macro printdsn(dsn=sasuser.courses,vars=course_code course_title days); proc print data=&dsn; var &vars; title "Listing of %upcase(&dsn) data set"; run; %mend; %printdsn() /*调用参数为默认参数的情况*/
3.3:Macros That Include Mixed Parameter Lists
All positional parameter variables in the %MACRO statement must be listed before any keyword parameter variable is listed
所有位置参数要列在关键字参数前(调用时原则也是这样)
4:理解符号表
全局符号表的生存周期
The global symbol table is created during the initialization of a SAS session and is deleted at the end of the session
?? are available anytime during the session
?? can be created by a user
?? have values that can be changed during the session (except for some automatic macro variables).
创建全局宏变量的几种方式
?? a %LET statement (used outside a macro definition)
?? a DATA step that contains a SYMPUT routine
?? a SELECT statement that contains an INTO clause in PROC SQL
?? a %GLOBAL statement.
The %GLOBAL statement
能定义多个全局宏,可以再宏定义中也可以在宏定义外,对已经生成了的宏无用
局部宏的生存周期
A local symbol table is created when a macro that includes a parameter list is called or when a request is made to create a local variable during macro execution. The local symbol table is deleted when the macro finishes execution
一句话:the local symbol table exists only while the macro executes.
局部宏的创建方式
?? parameters in a macro definition
?? a %LET statement within a macro definition
?? a DATA step that contains a SYMPUT routine within a macro definition
?? a SELECT statement that contains an INTO clause in PROC SQL within a macro definition
?? a %LOCAL statement.
着重介绍%local
只能在宏定义中出现,能定义多个变量,对已存在的变量无效
%let dsn=sasuser.courses;/*全局宏*/ %macro printdsn; %local dsn;/*局部*/ %global hehe;/*全局*/ %let dsn=sasuser.register; %let hehe = ‘say hehe‘; %put The value of DSN inside Printdsn is &dsn; %mend; %printdsn %put The value of DSN outside Printdsn is &dsn;
全局变量与局部变量的关系
这里的关系和c++中的作用域类似,当全局和局部中有同名变量时,局部覆盖全局,越局部,越优先考虑使用局部的变量。
这里做个例子来描述全局宏与局部宏的关系
宏的更新机制如下:如果在局部出现就先看看局部符号表中有没有对应变量(有就更新),没有就看全局(有就更新),没有就创建一个局部变量
下例中,dsn在全局有,所以更新全局的,但是这里要注意了,前一个put输出的是register后一个无输出,为啥?
因为在宏中更新的全局符号表中的值,当宏执行完后,自动销毁了,所以第二个put输出为缺失
如果将注释去掉,那么就以为着新建了一个局部变量,这样输出的值就各是各的了!
options symbolgen; options nomlogic; %let dsn=sasuser.courses; %macro printdsn; *%local dsn; %let dsn=sasuser.register; %put The value of DSN inside Printdsn is &dsn; %mend; %printdsn %put The value of DSN outside Printdsn is &dsn;
5:条件运算符
这里就是普通的运算符前面加%,nothing important to say
6:在宏中进行运算
6.1:The %EVAL function(不支持小数运算)
?? translates integer strings and hexadecimal strings to integers.
?? translates tokens representing arithmetic, comparison, and logical operators to macro-level operators.
?? performs arithmetic and logical operations.
The %EVAL function does not convert the following to numeric values:
?? numeric strings that contain a period or E-notation
?? SAS date and time constants.
6.2:%sysevalf function支持小数运算
%macro figureit(a,b); %let y=%sysevalf(&a+&b); %put The result with SYSEVALF is: &y; /*101.59*/ %put BOOLEAN conversion: %sysevalf(&a +&b, boolean); /*1*/ %put CEIL conversion: %sysevalf(&a +&b, ceil);/*102*/ %put FLOOR conversion: %sysevalf(&a +&b, floor);/*101*/ %put INTEGER conversion: %sysevalf(&a +&b, integer);/*101*/ %mend figureit; %figureit(100,1.59)