楼主: pobel
24778 44

[原创博文] 关于Macro Variable   [分享]

院士

12%

还不是VIP/贵宾

-

威望
2
论坛币
14788 个
通用积分
8.0001
学术水平
925 点
热心指数
925 点
信用等级
727 点
经验
113290 点
帖子
1289
精华
4
在线时间
3544 小时
注册时间
2008-12-10
最后登录
2019-11-27

初级热心勋章 中级热心勋章 初级信用勋章 初级学术勋章 中级信用勋章 中级学术勋章 高级热心勋章 高级学术勋章

pobel 发表于 2014-1-3 15:43:47 |显示全部楼层
(楼 1 of 2)
Creation of Macro Variable

在SAS中,宏变量可以在data lines之外的任何地方使用,一般来说宏变量的产生有以下情况:

_AUOMATIC_

SAS启动时,会自动产生一些宏变量。如SYSDATE、SYSDAY、SYSTIME、SYSUSERID、SYSVER、SYSMACRONAME等等。可以通过运行%put _automatic_;查看。

_automatic_ macro variable中,有些值是固定的,如SYSDATE和SYSTIME的值分别是SAS启动时的日期和时间;有些值是可以变化的,比如SYSLAST保存的是最后被创建的数据集的名字。


%LET variable=value;

%LET语句是定义宏变量最为直观的方法。如果%LET语句指定的宏变量不存在,则SAS会创建该宏变量;如果该宏变量已经存在,那SAS会更新宏变量的值。

用%LET对宏变量赋值时不需要用引号,如果使用了引号,引号会作为值的一部分。

%LET赋值时,等号右边的值没有所谓的数据类型之分,而是都会被作为字符处理,不会进行运算。例如 %let x=1+1;,宏变量x的值是1+1,而不是2。(可以通过运用宏函数,如%EVAL()等,来进行运算)

CALLSYMPUT () / CALL SYMPUTX ()

CALLSYMPUT () 和CALL SYMPUTX ()可以实现在DATA步的执行过程中创建宏变量。二者的主要区别在于CALL SYMPUTX ()会将第二个参数值前面和后面的空格去掉;并且CALL SYMPUTX ()有第三个参数来限定宏变量存放的位置。

关于CALL SYMPUT ()有一条几乎人尽皆知的规则是:不可以在同一个DATA步中“引用”CALL SYMPUTX ()创建的宏变量,但可以在同一个DATA步中“使用”。比如:

%symdel userid/nowarn;

data test;

    call symputx("userid","&sysuserid");

    userid1="&userid";

    userid2=symget("userid");

    put userid1= ;

    put userid2= ;

run;


上面的例子中userid1="&userid";这一句会产生一条WARNING,而userid2=symget('userid');这一句能够正常执行。其原因在于:

  • CALL SYMPUTX ()创建宏变量是在DATA步的执行阶段;
  • userid1="&userid";这句要求在DATA步的编译阶段就得到userid的值,而此时该宏变量还未被创建;
  • SYMGET() 是在DATA步执行阶段运行到该句时才去找宏变量的值,其参数只是宏变量的名字,而不需要&符号。

PROC SQL

PROC SQL的INTO子句可以将变量的值存到宏变量中:

select avg(weight) into :mvar from sashelp.class;

    §  会计算sashelp.class中各条记录的平均体重,并存入宏变量mvar中。

select name into :mvar1 -:mvar99 from sashelp.class

    §  这一句会将变量name的值依次存入宏变量mvar1,mvar2,…

    §  由于sashelp.class只有19条记录,这一句也就只会创建mvar1 - mvar19这19个宏变量。

    §  如果from子句后跟上order by name desc;,那么的mvar1值就会是倒序排列的第一个name值William,而mvar19的值将会是Alfred。

select name into :nmlist separated by ", " from sashelp.class

     §  这句会将变量name的各个值用", "来分隔,并存入到宏变量nmlist中。同样,where和order by分别会改变name的个数和顺序。


SAS在执行完每一个PROC SQL步之后,都会产生或更新某些宏变量如SQLOBS、SQLOOPS、SQLRC等,比较常用的是SQLOBS,这个宏变量的值可以是SQL选出的或删除的观测数。例如:

proc sql noprint;

  *** Number of rows selectd;

   create table boys as

     select *

      from sashelp.class

        where sex="M";

   %put ----Number ofboys in sashelp.class: &sqlobs;

  *** Number of rowed deleted;

   delete from boys where name eqt "J";

   %put ----Number ofboys whose name starts with "J": &sqlobs;

   

  *** Number of rows involved in creating macro variablelist;

   select Name into :name1-:name999

      from sashelp.class

       where age=12;

   %put ----Number ofstudents who is 12 years old: &sqlobs. ;

quit;


SYSPBUFF

SYSPBUFF是一个_AUTOMATIC_ macro variable。但这个宏变量不能在open code里使用,只能在宏里面使用,通常情况下是要在定义宏程序的时候使用PARMBUFF选项。在宏内使用这个宏变量时,SYSPBUFF记录的是在调用宏的时候所提供的参数的值,包括从左括号到右括号的所有字符在内。通过使用PARMBUFF,可以实现在调用宏的时候参数的个数和参数值更加灵活,而且并不影响正常的参数值的传递。

这里需要注意的是:通常在调用宏时,后面不需要加一个“多余的”分号,然而如果定义宏时使用了PARMBUFF,那在调用时SAS会“等待”后面将要赋给SYSPBUFF的值。因此,在调用一个没有参数的宏(类似%macro a/parmbuff;),并且不需要传给SYSPBUFF任何值的时候,需要在宏名字后加一个分号来表示调用的结束%a;

具体可以看下面的例子:

*** Without parameters;

%macro a/parmbuff;

  %put --Value of SYSPBUFF:&syspbuff;

%mend;

%a;

%a()

%a(haha)

%a(one=1,two,three is 3)


*** With name-style parameters;

%macro b(ds,var)/parmbuff;

    %put --Value of SYSPBUFF: &syspbuff;

     %put --Value of Parameters: &ds &var;

%mend;

%b(a,b)

%b(d,e,f,g)


*** With keyword-style parameter;

%macro c(var=)/parmbuff;

  %put --Value of SYSPBUFF:&syspbuff;

  %put --Value of Parameters: &var;

%mend;

%c(var=adsdsas)

%c(,,whatever you want vars=sa)


Other


  • Macro Parameters
    如果定义宏时使用了参数,那在宏执行的过程中,参数都会作为宏变量存在。
  • %do i=1 %to 5; ...   %end;
    %do语句中的指示变量 i 也是宏变量。
  • 下面的语句会对sashelp.class中的每个变量都创建相同名字的宏变量,并保存该变量在第十行记录的值。

%let dsid=%sysfunc(open(sashelp.class,i));

%syscall set(dsid);

%let rc=%sysfunc(fetchobs(&dsid,10));

%put _user_;

%let rc=%sysfunc(close(&dsid));

关键词:Variable Macro ABLE ABL acr

回帖推荐

soporaeternus 发表于20楼  查看完整内容

batch mode 下-sysparm 可以完成OS和SAS的参数传递,生global的&sysparm 算对宏产生做个补充

webgu 发表于6楼  查看完整内容

我再加一点东东。 1. 除了%symglobl ,%symlocal , 比较常用的还有%symexist 来判定宏变量是否存在。 2. 同时,在Data 步,也有一些类似的函数。如 symglobl(),symlocal(),symexist() 等data step function for macro. symget() 就是其中之一。 不过还有一个其强悍的函数: resolve(). 不仅可以解析宏变量、宏、还可以是DATA步变量及其组合。 3. 一些好用的关于宏的系统option. mprint ,symbolgen,mcompile, mstored sas ...
已有 12 人评分经验 论坛币 学术水平 热心指数 信用等级 收起 理由
eijuhz + 1 精彩帖子
klfai + 5 + 2 + 2 + 2 分析的有道理
kmrd + 50 精彩帖子
Tigflanker + 1 + 1 + 1 精彩帖子
soporaeternus + 5 + 5 + 5 batch mode 下-sysparm 可以完成OS和SAS的参.
zhangibt + 1 + 1 精彩帖子
dxystata + 100 + 1 + 1 + 1 精彩帖子
客初 + 36 + 2 + 3 + 2 精彩帖子
lachance + 1 + 1 + 1 精彩帖子
webgu + 5 pobel出品,品牌保证。

总评分: 经验 + 286  论坛币 + 105  学术水平 + 24  热心指数 + 25  信用等级 + 24   查看全部评分

本帖被以下文库推荐

和谐拯救危机
stata SPSS
pobel 发表于 2014-1-3 15:43:48 |显示全部楼层

(楼 2 of 2)

Scopeof Macro Variable


SAS中的宏变量可以分为Global和Local两类。分别存放于Global Symbol Table和Local Symbol Table。


Global Symbol Table只有一个,在SAS进程开始时被创建,在进程结束时删除。


Local Symbol Table在宏开始执行时创建,宏执行完毕后删除,每一个宏在执行时都会有各自的Local Symbol Table。


Global的宏变量自被创建起,直至被删除或当前SAS进程结束,都会存在;并且可以在open code或宏的内部使用。而local的宏变量只是在宏执行过程中存在,只能在宏的内部使用。


_AUOMATIC_宏变量


SAS启动时所创建的_automatic_宏变量中,除了SYSPBUFF之外,都是Global的。SYSPBUFF的情况比较特殊,通过下面的例子我们可以总结SYSPBUFF的特点如下:


·  在open code中运行%put _automatic_; 可以看出SYSPBUFF属于_automatic_;

·  SYSPBUFF只有在宏运行的时候才会存在,因此不能在open code中输出或改变它的值。而在宏定义中,通过下面的方式都可以使SYSPBUFF存在或改变它的值:
     * 使用%LET语句更新SYSPBUFF的值,%LET语句之后执行%put _automatic_;会发现SYSPBUFF的值已经改变。
     * 使用%local syspbuff;(这种用法是不正常的,在这里仅仅是为了测试SYSPBUFF的scope)。
     * 使用/parmbuff,这种是使用SYSPBUFF的常规方法,而且会在宏开始执行时便为SYSPBUFF赋值。

·  通过使用%SYMGLOBL和%SYMLOCAL可以判断:
     * 在open code中SYSPBUFF在Global Symbol Table中不存在。
     * 在宏执行过程中,SYSPBUFF总是存在于Global Symbol Table,而不是Local Symbol Table中,即便是使用了%local syspbuff;。

%put _automatic_;

%put &syspbuff;

%let syspbuff=aaa;

%put Is SYSPBUFF Global?: %symglobl(syspbuff);


%macro test;

   %put ---SYSPBUFF: &syspbuff;


   %let syspbuff=aaaaa;

   %put _automatic_;

   %put ---SYSPBUFF: &syspbuff;


   %put ;

   %put ---Is SYSPBUFF Global?: %symglobl(syspbuff);

   %put ---Is SYSPBUFF Local?: %symlocal(syspbuff);

%mend;

%test


%macro test1;

    %local a b c syspbuff ;

    %put ---SYSPBUFF: &syspbuff;


    %put ;

    %put ---Is SYSPBUFF Global?: %symglobl(syspbuff);

    %put ---Is SYSPBUFF Local?: %symlocal(syspbuff);

%mend;

%test1


%macro test2(var)/parmbuff;

   %put ---SYSPBUFF: &syspbuff;


   %put ;

   %let syspbuff=hahaha;

   %put ---SYSPBUFF: &syspbuff;


   %put ;

   %put ---Is SYSPBUFF Global?: %symglobl(syspbuff);

   %put ---Is SYSPBUFF Local?: %symlocal(syspbuff);

%mend;

%test2(abcde,dsn=class)


如果宏变量已经存在

当SAS为一个宏变量赋值时,SAS会从里到外(即从最内层的Local Symbol Table一直到Global Symbol Table)查找该宏变量是否已经存在。如果SAS在某个位置找到了这个宏变量,就会执行赋值操作,查找的动作也随即停止。比如:

%symdel i tmp/ nowarn;

%let i=1;

%let tmp=value from open code.;


%macro inner(i_value);

    %let tmp=value from inner;

    %let i=&i_value;


    %put _local_;

%mend;


%macro outer;

    %local tmp;  

    %let tmp=value from outer;


    %let i=2;


     data test;

        v=3;

        call symputx("i",v);

     run;


     proc sql noprint;

        select distinct "4" into :i from test;

     quit;


    %do i=5 %to 100;

    %end;


    %inner(1000)


     %put _local_;

%mend;


%outer

%put Now value of macro variable i is: &i;

%put Now value of macro variable tmp is:&tmp;

上面的例子中:

·  对于宏变量i,无论是CALL SYMPUTX(),  PROC SQL, 还是%LET 或%DO语句,当它们试图为宏变量i赋值时,所改变的总是Global Symbol Table中的宏变量i的值。宏outer和inner在执行时都没有在自己的Local Symbol Table中创建宏变量 i 。

·  对于宏变量tmp,由于宏outer中有local的宏变量tmp,所以inner执行时改变的是宏outer中的tmp的值,而不能改变Global Symbol Table 中tmp的值。


如果宏变量不存在

当SAS对宏变量赋值时,如果宏变量不存在:

1. %LET语句会在当前位置创建宏变量。如果是在open code中,则创建global的宏变量,如果是在宏中,则会为%LET语句所在的宏创建local的宏变量。


2. %DO语句会在所在的宏创建local宏变量。


3.宏中的PROCSQL INTO语句会创建local的宏变量。


4.宏中的参数会作为宏的local宏变量。


5. CALL SYMPUT () 会在离它所在的DATA步最近的,并且非空的symbol table创建宏变量。也就是,如果DATA步执行时Local Symbol Table 中已经有宏变量,则CALLSYMPUT () 会将宏变量创建在LocalSymbol Table中。否则就会向外层查找,直到Global Symbol Table. 下面的特殊情况可以使CALLSYMPUT () 创建local的宏变量:


  • 宏定义中使用了PARMBUFF选项。SAS帮助文档中的说法是” If an executing macro uses &SYSPBUFF and SYMPUT to create a macro variable, the macro variable is created in the local symbol table.” 这应该是不严谨的,比如:
%symdel var /nowarn;

%macro test;

   %let syspbuff=bbbb;

   data _null_;

      call symput("var","&syspbuff");

   run;


   %put _local_;


   %put ---Is VAR Global?: %symglobl(var);

   %put ---Is VAR Local?: %symlocal(var);

%mend;

%test

  • 宏定义中包含computed %GOTO语句。
%symdel var/nowarn;

%macro test;

   %put _local_;

   data _null_;

      call symput("var","bbbbb");

   run;


   %put _local_;


   %let home=last;

   %goto &home;

   %last:

%mend;

%test

  • SAS 帮助文档里还有一条是“Beginning with Version8, if SYMPUT is used after a PROC SQL, the variable will be created in a localsymbol table.”这里有一点是需要注意的:在调用这个宏之前,如果在open code里已经执行过PROCSQL语句,而且宏里面的PROC SQL没有用到INTO子句创建新的宏变量的话,那CALL SYMPUT ()是不会将宏变量创建到Local Symbol Table的。原因在于PROC SQL所自动产生的SQLOBS,SQLRC等宏变量已经在Global Symbol Table 存在,因此宏里面的PROC SQL再运行的话也不会产生local的宏变量。这样CALLSYMPUT ()运行时LocalSymbol Table 还是空的,所以不会为当前宏创建local的宏变量。:
%symdel var/nowarn;

proc sql; quit;

%macro test;

   proc sql;

      create table class as

        select distinct * from sashelp.class;

     quit;


   data _null_;

      call symput("var","aaaa");

   run;

   %put _local_;

   %put ---Is VAR Global?: %symglobl(var);

   %put ---Is VAR Local?: %symlocal(var);

%mend;


%test


%symdel var sqlobs/nowarn;

%test
已有 5 人评分学术水平 热心指数 信用等级 收起 理由
co_fund + 1 + 1 + 1 精彩帖子
512002855 + 2 精彩帖子
420948492 + 2 + 1 精彩帖子
eric_darcy + 1 + 1 + 1 POBEL犀利阿~佩服
Tigflanker + 1 + 1 + 1 第二部分看着就有点小晕了

总评分: 学术水平 + 7  热心指数 + 4  信用等级 + 3   查看全部评分

和谐拯救危机
回复

使用道具 举报

webgu 发表于 2014-1-4 09:31:23 |显示全部楼层
Pobel总是那么系统,全面,且循序渐进,深入浅出。
佩服。
SAS资源
1. SAS 微信:StatsThinking
2. SAS QQ群:348941365
回复

使用道具 举报

天堂之路 发表于 2014-1-4 09:48:48 |显示全部楼层
回复

使用道具 举报

linggol 发表于 2014-1-4 10:09:19 |显示全部楼层
强烈支持  版主  好东西 学习了!
回复

使用道具 举报

webgu 发表于 2014-1-4 10:33:42 |显示全部楼层
我再加一点东东。

1. 除了%symglobl ,%symlocal , 比较常用的还有%symexist 来判定宏变量是否存在。

2. 同时,在Data 步,也有一些类似的函数。如 symglobl(),symlocal(),symexist() 等data step function for macro. symget() 就是其中之一。 不过还有一个其强悍的函数: resolve(). 不仅可以解析宏变量、宏、还可以是DATA步变量及其组合。

3. 一些好用的关于宏的系统option.  mprint ,symbolgen,mcompile, mstored sasmstore=

已有 3 人评分学术水平 热心指数 信用等级 收起 理由
raindewRD + 1 + 1 + 1 观点有启发
Tigflanker + 1 + 1 + 1 resolve
pobel + 5 + 5 + 5 多谢版主补充

总评分: 学术水平 + 7  热心指数 + 7  信用等级 + 7   查看全部评分

SAS资源
1. SAS 微信:StatsThinking
2. SAS QQ群:348941365
回复

使用道具 举报

lachance 发表于 2014-1-4 10:49:46 |显示全部楼层
学习啦,多谢
[
回复

使用道具 举报

lxpddws 发表于 2014-1-4 11:04:52 |显示全部楼层
回复

使用道具 举报

一生有你a 发表于 2014-1-4 21:23:35 |显示全部楼层
回复

使用道具 举报

天堂之路 发表于 2014-1-4 21:58:53 |显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 我要注册

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2019-12-11 23:30