前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SAS-Macro 中的那些语句(四)

SAS-Macro 中的那些语句(四)

作者头像
Setup
发布2019-10-20 18:44:58
3.8K0
发布2019-10-20 18:44:58
举报

这还是继续前面的基础说,今天来说一说宏中数值运算、几个常见函数等...

宏数值运算

大家都知道SAS数据集中的变量是分数值型、字符型的。那么SAS的宏变量是否分数值型变量和字符型变量呢?是不分的,那么宏变量的计算是直接算么?当然是不是的,宏变量的计算是有俩个关键词%eval(只能进行整数的运算),%sysevalf(可进行整数运算与小数运算)....

data _null_;
  call symput('mvar1','1.213');
  call symput('mvar2','2.1');
  call symput('mvar3','99999');
  call symput('mvar4','333');
  call symput('mvar5','21');
run;

  /*********************************

    %eval只支持整数的运算

  **********************************/
  %put  NOTE:'%eval(&mvar5.-&mvar2.)=' %eval(&mvar5.-&mvar2.);/*会有ERROR*/
  %put  NOTE:'%eval(&mvar5.-&mvar2.)=' %eval(&mvar4.-&mvar5.);
  %put  NOTE:'%eval(&mvar5.*&mvar4.)=' %eval(&mvar5.*&mvar4.);
  %put  NOTE:'%eval(&mvar5.*&mvar2.)=' %eval(&mvar5.*&mvar2.);/*会有ERROR*/
  /*********************************

    %SYSEVALF支持浮点运行

  **********************************/
  %put  NOTE:'%SYSEVALF(&mvar5.-&mvar2.)=' %SYSEVALF(&mvar5.-&mvar2.);
  %put  NOTE:'%SYSEVALF(&mvar4.-&mvar5.)=' %SYSEVALF(&mvar4.-&mvar5.);
  %put  NOTE:'%SYSEVALF(&mvar5.*&mvar4.)=' %SYSEVALF(&mvar5.*&mvar4.);
  %put  NOTE:'%SYSEVALF(&mvar5.*&mvar2.)=' %SYSEVALF(&mvar5.*&mvar2.);

%eval进行运算的宏变量有小数点是会有Error的...那么来看看日志。

%sysfunc

前几天小编推送了一大堆SAS里面的基础函数,那么那些函数在宏是否可以用呢?可以用的,不过需要用一个东西包裹起来...是什么东西呢?那就是%sysfunc(),很简单的...那么来看看一个例子,更加直接的理解函数...

data _null_;
  call symput('mvar1','1.213');
  call symput('mvar2','2.1');
  call symput('mvar3','99999');
  call symput('mvar4','333');
  call symput('mvar5','21');
run;
  /*********************************

    宏中用SAS普通的函数(%sysfunc()包裹起来,中间放SAS中的普通函数)

  **********************************/
  %put  NOTE:'%sysfunc(Max(&mvar5.,&mvar1,&mvar2,&mvar3,&mvar4))=' %sysfunc(Max(&mvar5.,&mvar1,&mvar2,&mvar3,&mvar4));
  %put  NOTE:'%sysfunc(min(&mvar5.,&mvar1,&mvar2,&mvar3,&mvar4))=' %sysfunc(min(&mvar5.,&mvar1,&mvar2,&mvar3,&mvar4));

例子举的是Max与Min函数...除了加了%sysfunc包裹起来,其他的和都没区别和变化....

宏中的函数

那么宏中的函数必须用%sysfunc()包裹起来么,不是的。SAS还将几个常用的函数直接变成了宏函数,都有那几个常用的函数呢?%length,%index,%substr,%scan,%upcase,这几个常见的函数...除了加了一个%,其他的都没变化...如果记性好的朋友,并且看过上一篇推送的朋友,注意发现细节的朋友...好像没有这样的朋友

应该会注意到昨天%do...%while的例子中小编用了一个%qscan函数...为啥%scan多了一个q呢?还是先看看例子...

%macro test;
%let dslist=ds1\sheetname1\contents1\title1|ds2\sheetname2\contents2\title2|ds3\sheetname3\contents3\title3;
%let i=1;
%do %while(%qscan(&dslist,&i,|)^=%str());
 %let list&i=%qscan(&dslist,&i,|);
 %let dsn&i=%qscan(&&list&i.,1,\);
 %let sht&i=%qscan(&&list&i.,2,\);
 %let cnt&i=%qscan(&&list&i.,3,\);
 %let tle&i=%qscan(&&list&i.,4,\);
 %put NOTE:循环次数(&i.) &&dsn&i &&sht&i &&cnt&i &&tle&i;
 %let i=%eval(&i+1);
%end;    
 %let _loop=%eval(&i-1);
%mend;
%test

看吧,是不是用的%qscan,那么他们的区别的啥呢,在SAS中有一些特殊字符,如:&,%...等,这个能干嘛呢?能屏蔽掉一些特殊字符....可能这里并不能很好的体现那么小编在网上找了2个简化的例子...

%macro test();
%let mvar1=%nrstr(四海/翻腾/云水怒&九州/震荡/风雷激);
%let mvar2=&mvar1.;
%let i=1;
   %do %while ( %qscan(&mvar2.,&i.,"/") ne %str( )  );
       %let msg=%qscan(&mvar2.,&i.,"/");
       %put NOTE: &msg.;
       %let i=%eval(&i.+1);
   %end;

%let i=1;
   %do %while ( %scan(&mvar2.,&i.,"/") ne %str( )  );
       %let msg=%scan(&mvar2.,&i.,"/");
       %put NOTE: &msg.;
       %let i=%eval(&i.+1);
   %end;

%mend;
%test;

小编将这个%qscan,与%scan放到一起做比对,当执行到%scan某处的时候,会因为错误造成宏的终止....为啥会终止呢,那是因为里面存在特殊字符&。%qscan相对来说较常见...其他的还有几个大概都一样吧,因为小编也没用过,只用过%qscan..还是来看一下日志...

宏变量的解析

其实宏变量的解析应该放到很前面说的,不过宏变量的解析也是太简单了,例子看俩个就能自己领悟的...所以也没打算说。。不过为了引出另外的一个关键词,还是浅谈一下...毕竟,一般公司在笔试应届毕业生SAS programmer、或者应届毕业生转正考试的时候经常会遇到宏变量解析的笔试题...那么久来看看几个简单的例子

%let i=1;
%let m=2;
%let m1=你好;
%let m12=我好;

/*单个解析:用宏变量在日志打印出 1*/
%put NOTE:&I;
%put NOTE:%superq(I);
/*单个解析:用宏变量在日志打印出 12*/
%put NOTE:&I&M;
%put NOTE:%superq(I)%superq(M);
/*双重解析:用宏变量在日志打印出 你好*/
%put NOTE:&&M&i;
%put NOTE:%superq(m&i);
/*多重解析:用宏变量在日志打印出 我好*/
%put NOTE:&&M&i&m;
%put NOTE:%superq(m&i&m);

这儿的日志就不贴了...

%superq() 解析括号内作为一个整体的宏变量,

这个关键词可以起到解析宏变量的作用,当然此处还没有完全的体现出%superq在SAS中的真正的应用....

data _null_; 
  call symput('msg', '你真美!'); 
  call symput('macvar1', 'msg&msg'); 
run; 
%put NOTE: &macvar1.;
%put NOTE: %superq(macvar1);

有时候,我们不需要解析macvar1 中的&符号..此时就可以用%superq进行操作...

现在又要说到上一篇的一个例子,%return中的一个,那么现在再来看一个下这个例子...

%macro  test(inds);

%if %sysfunc(exist(%superq(inds))) eq 0  %then  %do;
%put NOTE:你输出数据集(%superq(inds))不存在...请核查!;
%return;
%end;

%put NOTE:你输出数据集(%superq(inds))不存在,该宏继续执行...;
%mend;


%test(a);
%test(SASHELP.CLASS);

%put NOTE:即将见证奇迹的时刻了...;
%let ss=SASHELP.CLASS;
%test(&ss.);

猜一猜即将见证奇迹后面的代码执行,会有什么效果?据说%superq作用在执行期,SAS程序的执行是先编译在执行...猜完了,在来看看日志...

奇怪不奇怪?为啥第一条横向的那个地方没有解析出SASHELP.CLASS数据集,而第二条横向却解析出了数据,到底是啥?

我也不太清楚...小编现在境界不够!还理解不了这些,那么所以说:%superq要用在合适的场合~程序语言都要慎用...

Quoting

上面,已经遇到了一个小编解释不出来的东西,那么接下还有...

%str()/%nrstr()/%bquote/%nrbquote...这些都是干嘛的呢,%str()与%nrstr()可以在小编的历史推送中的例子时长出现,这个俩个是作用在编译期间,可以屏蔽一些特殊符号,%bquote/%nrbquote作用在执行期间,同样可以屏蔽一些特殊符号,所以前面俩个和后面俩个区别在于作用的期间....那么带有nr与不带有nr之间又有什么区别呢?NR=NOT Resolved,带有NR比不带NR多屏蔽俩个特殊字符(&、%)...其他就没啥区别了...

关于这几个小编见识不够...所以自己就不写自己的理解了...小编还要请教各位大神一个问题....(先给大家分享几个去处,可以看一看别人分享的这部分的内容:第一个去出:SAS中文论坛(微信公众号)-精品推荐-SAS百家讲坛-言论里面,第二个去出:知乎(SAS IN PHARMA)-一个叫木鱼的大神发的帖子...里面的帖子好像全是这个大神发的...非常不错的帖子...)那么在来看看我的问题..

data _null_;
  call symput('mac', '%str(&sss)'); 
  call symput('mac1', '%nrstr(&sss)'); 
  call symput('mac2', '%bquote(&sss)'); 
  call symput('mac3', '%nrbquote(&sss)'); 
run;
%put NOTE:&mac.;
%put NOTE:&mac1.;
%put NOTE:&mac2.;
%put NOTE:&mac3.;

这里我没有定义&sss宏变量,我的问题是为啥日志的警告是1,0,2,1...我这这样的瞎想的,想的我自己还以为是真的(肯定不是真的)....

/*

1次警告原因:在 %put NOTE:&mac.;进行编译的时候,发现&mac存在,便开始进行执行,在执行过程中,先将&mac解析成%str(&sss)
此时,由于%str()作用在编译期间,且不对&符号进行屏蔽,此时保出了一个警告,便将&sss当做一个字符串,进行了执行...
*/
%put NOTE:&mac.;
/*
0次警告原因:在 %put NOTE:&mac1.;进行编译的时候,发现&mac存在,便开始进行执行,在执行过程中,先将&mac解析成%nrstr(&sss)
此时,由于%nrstr()作用在编译期间,且对&符号进行屏蔽,便将&sss当做一个字符串,进行了执行...
*/

%put NOTE:&mac1.;
/*
2次警告原因:在 %put NOTE:&mac2.;进行编译的时候,发现&mac存在,便开始进行执行,在执行过程中,先将&mac解析成%bquote(&sss)
此时,由于%bquote()作用在执行期间,且不对&符号进行屏蔽,发现&sss不存在便报出了一次警告,由于%bquote()的存在,造成了未知因素的干扰,
并未将&sss作为字符串,进行了执行,在执行时又发现了&sss不存在...
*/

%put NOTE:&mac2.;
/*
1次警告原因:在 %put NOTE:&mac3.;进行编译的时候,发现&mac存在,便开始进行执行,在执行过程中,先将&mac解析成%nrbquote(&sss)
此时,发现&sss不存在便报出了一次警告,进行了执行,但由于%nrbquote()作用在执行期间,且对&符号进行屏蔽,将&sss当做了字符串,所以只有编译那一次的警告...
*/
%put NOTE:&mac3.;

这个问题是怎么来的呢?这个问题是另外的一个问题的简化版,那么来看下另外的一个问题....

这里的ERROR:2,3,1应该怎么理解呢....就是上面的那个问题的简化版...

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-02-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 SAS程序分享号号号 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档