楼主: fisheryou
6620 16

[问答] 关于坛子中CALL EXECUTE()用法产生的疑惑 [推广有奖]

  • 1关注
  • 2粉丝

已卖:103份资源

副教授

9%

还不是VIP/贵宾

-

威望
0
论坛币
7591 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
42160 点
帖子
217
精华
0
在线时间
1209 小时
注册时间
2010-5-5
最后登录
2021-8-12

楼主
fisheryou 发表于 2013-8-1 15:33:54 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
原贴:https://bbs.pinggu.org/thread-2377205-1-1.html
写的很精彩,但是试了一下,发现有些出入,可能是我水平有限,请帮助

“如果CALL EXECUTR()的参数中有宏语句,那么宏语句在何时执行会有三种情况:

1.        如果宏语句在双引号中并没有使用%NRSTR(),宏语句会在DATA步编译阶段执行;
2.        如果宏语句在单引号中,或者在双引号中并使用了%NRSTR(),宏语句会在DATA步执行阶段执行;
3.        如果宏语句在单引号中,并且使用了%NRSTR(),则宏语句会在DATA步执行完之后执行。”



下面这段代码如何解释,谢谢:
  1. %macro test();
  2.         proc print data=a;
  3.         run;
  4. %mend;
  5. %test();

  6. data a;
  7. set sashelp.class end=last;
  8. if _n_=1 then call execute("%test()");
复制代码

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:EXECUTE Cute call ECU cut 单引号 双引号 如何

沙发
pobel 在职认证  发表于 2013-8-1 16:31:42
楼主的例子中,call execute()中所调用的宏是在编译阶段执行的。宏的执行结果是“proc print data=a;run;”
所以,SAS对这个data步编译完成后就变成:
data a;
        set sashelp.class end=last;
        if _n_=1 then call execute("proc print data=a; run;");
run;

如果在宏定义中加入宏语句的话,那该宏语句也会在编译时执行。例如:
%macro test();
        proc print data=a;
        run;
      %let value=9999;
%mend;


%let value=1111;

data a;
        set sashelp.class end=last;
        if _n_=1 then call execute("%test()");
        value="&value";
run;
和谐拯救危机

藤椅
boe 发表于 2013-8-2 02:55:59
  1. data a;
  2. set sashelp.class end=last;
  3. put _all_;
  4. call execute("%test()");
  5. run;
  6. 觉得楼上大侠说得很对啊!
复制代码
Gorgeous girl , I love !

板凳
zhou.wen 发表于 2013-9-11 13:25:42
pobel 发表于 2013-8-1 16:31
楼主的例子中,call execute()中所调用的宏是在编译阶段执行的。宏的执行结果是“proc print data=a;run;” ...
不知道pobel大神有没有用过dosubl 函数
http://support.sas.com/resources ... ings13/032-2013.pdf
1.下面这段代码虽然可以通过,但是我对宏编译,跟data不编译的顺序不太清楚,希望可以得到你的讲解
代码是源于坛里的讨论贴
https://bbs.pinggu.org/thread-2614881-1-1.html
%macro main;
data b;
array a(1000) $ ;
do i=1 to 1000;
a(i)=put(i,pib8.);
end;
e=addrlong(a(1));
call symputx("e",e);
_error_=dosubl( "
data a;
do i=1 to 12;
ans=peeklong(put(input('&e',pib8.)+8*(i-1),pib8.),8);
output;
end;
run;
quit;
");
run;
%mend;

%main;
Practice Is The Best Teacher!

报纸
pobel 在职认证  发表于 2013-9-11 14:07:38
zhou.wen 发表于 2013-9-11 13:25
不知道pobel大神有没有用过dosubl 函数
http://support.sas.com/resources/papers/proceedings13/032-20 ...
我没有用过dosubl函数,按照介绍应该是能够实现在执行某个data步的过程中去执行另外一个data步。

在你给出的例子中,dosubl()参数中的ans=peeklong(put(input('&e',pib8.)+8*(i-1),pib8.),8);这一句中的宏变量e能够解析出来么?

(我不是指宏变量引用左右的单引号,而是指上面call symputx()中产生的宏变量e,能够在接下来的dosubl中直接引用?)
和谐拯救危机

地板
zhou.wen 发表于 2013-9-11 14:16:04
第一次运行都会报错
第二次运行有的时候成功,有的时候出错,我猜测是sas内部有缓存机制
下面的语句就不会出错
data b;
array a(1000) $ ;
do i=1 to 1000;
a(i)=put(i,pib8.);
end;
e=addrlong(a(1));
call symputx("e",e);
_error_=dosubl( "
data a;
do i=1 to 12;
ans=peeklong(put(input(symget('e'),pib8.)+8*2*(i-1),pib8.),8);
output;
end;
run;
quit;
");
run;
Practice Is The Best Teacher!

7
pobel 在职认证  发表于 2013-9-11 14:30:00
zhou.wen 发表于 2013-9-11 14:16
第一次运行都会报错
第二次运行有的时候成功,有的时候出错,我猜测是sas内部有缓存机制
下面的语句就不会 ...
如果dosubl()中直接引用宏变量‘&e’

第一次运行会报错是因为:call symputx()所产生的宏变量e需要到data b这个数据步运行完毕后才能直接引用。因此dosubl()中的代码如果用‘&e’ 则会提示找不到宏变量e。

之后的运行应该不会再提示宏变量e找不到,但‘&e’的结果是上次运行data b时所产生的宏变量e。
已有 1 人评分学术水平 热心指数 信用等级 收起 理由
zhou.wen + 1 + 1 + 1 热心帮助其他会员

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

和谐拯救危机

8
zhou.wen 发表于 2013-9-11 14:42:57
第二次运行有的时候可以得到想要的结果,有的时候不能
Practice Is The Best Teacher!

9
zhou.wen 发表于 2013-9-11 14:44:02
pobel 发表于 2013-9-11 14:30
如果dosubl()中直接引用宏变量‘&e’

第一次运行会报错是因为:call symputx()所产生的宏变量e需要到d ...
补充一下,前面我写代码也应该是比较好理解的,但是外部嵌套宏之后,宏的编译应该在data之前
因此,第一次运行%main;的时候宏变量e没有赋值,所以出错,但是第二次运行%main;后宏变量e已经赋了值,所以第二次运行结果正确
这里还有个小问题,宏变量e赋的是data b中变量a(1)的内存地址,我一开始理解data步结束后内存地址会释放,也就是说下次运行data b步的时候a(1)的地址应该有变化才对
但是从结果来看,第二次运行%main;宏变量e正确的取到了a(1)的内存地址,也就是说第二次运行data b的时候,虽然数据集是重新生成的,但是给变量a(1)分配的内存地址跟第一次运行相比并没有改变。于是我猜测可能是sas内部有缓存机制
下面做一些实验:
option nonotes nosource;
%put Firt Time Run:data a address is;
data a;
b=1;c=2;
add=addrlong(b);
put add hex16.;
run;
%put Firt Time Run:data a1 address is;
data a1;
x=1;y=1;z=2;
add=addrlong(x);
put add hex16.;
run;
%put Second Time Run:data a address is;
data a;
b=1;c=2;
add=addrlong(b);
put add hex16.;
run;
结果为:
Firt Time Run:data a address is
0881AA0C00000000
Firt Time Run:data a1 address is
3881AA0C00000000
Second Time Run:data a address is
0881AA0C00000000
可以猜测提交过的代码在,在sas中有缓存,所以相同的变量的内存地址没有发生变化,这样也就解释了为什么第二次运行%main;可以成功。
上面的大部分内容为个人理解,希望各路大神拍砖。
Practice Is The Best Teacher!

10
pobel 在职认证  发表于 2013-9-11 15:07:04
zhou.wen 发表于 2013-9-11 14:44
补充一下,前面我写代码也应该是比较好理解的,但是外部嵌套宏之后,宏的编译应该在data之前
因此,第一 ...
我对你提到的缓存机制不懂,希望有高手可以为你解惑。

我的疑问是:你的%main在第二次运行的成功与否应该是和宏变量e是不是已经存在有关系。

如果你在%macro main;的开始加上一句 %let mvar=anything;, 那你的%main还能成功运行么?(当然前提是,在第一次执行%main之前,宏变量e是不存在的)

%macro main;
%let mvar=anything;

data b;
array a(1000) $ ;
do i=1 to 1000;
a(i)=put(i,pib8.);
end;
e=addrlong(a(1));
call symputx("e",e);
_error_=dosubl( "
data a;
do i=1 to 12;
ans=peeklong(put(input('&e',pib8.)+8*(i-1),pib8.),8);
output;
end;
run;
quit;
");
run;
%mend;
和谐拯救危机

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

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2025-12-6 09:14