楼主: Tigflanker
3892 9

[问答] 如何从一个宏(或open code)获取另一个宏的某宏变量值 [推广有奖]

  • 8关注
  • 18粉丝

副教授

49%

还不是VIP/贵宾

-

威望
0
论坛币
2321 个
通用积分
9.9128
学术水平
179 点
热心指数
194 点
信用等级
167 点
经验
27443 点
帖子
622
精华
0
在线时间
851 小时
注册时间
2011-3-27
最后登录
2023-5-14

楼主
Tigflanker 发表于 2014-5-6 23:48:27 |AI写论文
50论坛币
更新:

谢谢大家的回复。

Global的确是解决办法,不过若是加了Global,那么我无论是在%put _user_还是在sashelp.vmacro中都可以找得到他的值。

我说下我最原始的想法:

一般我们在写一段程序的时候,像我喜欢在整段程序中加个很大的宏环境,这样就可以在一些过程步中使用例如%do,%if这些宏语句。例如:

data a;
   a = %if &type. eq C %then in;put( b , best.);
run;

但是当我调试整段程序的时候,我也许只想运行上面那个data步。

现在对于该步中存在的%do,我已经解决了:

  1. /*gSubmit "%inc '/user1/*****/Tools/FOC.sas';"*/

  2. filename temp_pgm temp;
  3. dm 'clear pgm;pgm;paste';
  4. dm pgm 'file temp_pgm replace' pgm;

  5. data temp_pgm;
  6.   infile temp_pgm truncover;
  7.   input temp_pgm $200.;
  8. run;

  9. data temp_pgm;
  10.   if 0 then set temp_pgm;
  11.   if _n_ = 1 then do;
  12.     temp_pgm = '%Macro For_Open_Code;';
  13.         output;
  14.   end;

  15.   set temp_pgm end = last;
  16.     output;

  17.   if last then do;
  18.     temp_pgm = '%Mend For_Open_Code;';
  19.         output;
  20.     temp_pgm = '%For_Open_Code;';
  21.         output;
  22.   end;
  23. run;

  24. filename temp_pg1 temp;
  25. data null_;
  26.   set temp_pgm;
  27.   file temp_pg1;
  28.   put temp_pgm $200.;
  29. run;
  30. %inc temp_pg1;
复制代码

这样,对于剪切板中的一段包含%do的data步,我就可以直接用我的快捷键给他加个宏环境来解析、运行它。

但是,面对data步中有的%if &type.,我需要知道宿主宏中的type为什么值,而我建议在主宏中加上范围声明。

所以。。。

我有些奇怪为什么像data或过程步中的%do,在open code中依然无法解析。(所知在9。2中仍然无法实现)

故出此问,谢谢 :)
————————————————————————————————————————————————————
想请问一下,我能否从一个宏,或者是Open Code来获取另一个宏的某个变量?
前提是不再次调用这个宏,当然这个宏已经被调用过一次。

例如:
%macro a;
  *So many statements;
  %let a = x;
  *So many statements;
%mend;

%a;

%macro b;
  *How can I get the value &a. from Macro a?;
  *Likes in JAVA style &a.a ;
%mend;

%b;



我试过%put _all_,但是这个a是local的,不知有何办法?
谢谢。

最佳答案

pobel 查看完整内容

对于楼主的例子: data a; a = %if &type. eq C %then in;put( b , best.); run; 如果楼主把这个data步放到了宏里面,是需要“调用”宏才能运行这个data步的。 所以只要把和宏变量type相关的语句也包括到宏里就可以了。 如果只是把这个data步放到%macro语句和%mend语句之间,我只能想到两种情况: 1. 宏变量type是global的; 2. 宏变量type在“更外层”的宏中赋值,并且需要调用type所在的“外层”宏。(只调用data ...
关键词:code Open Pen ODE COD 如何
Bye SAS.
若有缘,能重聚。

沙发
pobel 在职认证  发表于 2014-5-6 23:48:28
对于楼主的例子:
data a;
   a = %if &type. eq C %then in;put( b , best.);
run;

如果楼主把这个data步放到了宏里面,是需要“调用”宏才能运行这个data步的。
所以只要把和宏变量type相关的语句也包括到宏里就可以了。

如果只是把这个data步放到%macro语句和%mend语句之间,我只能想到两种情况:
1. 宏变量type是global的;
2. 宏变量type在“更外层”的宏中赋值,并且需要调用type所在的“外层”宏。(只调用data步所在的宏不能实现,因为如果不是global的话,那type只能存在于其所在宏“执行”过程中。如果不调用外层的宏,那所谓的type宏变量根本就不存在,更谈不上它的值了)
已有 1 人评分学术水平 热心指数 信用等级 收起 理由
Tigflanker + 1 + 1 + 1 分析的有道理

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

和谐拯救危机

藤椅
wwang111 发表于 2014-5-7 08:19:51
在最前面加一个 %global a;
已有 1 人评分学术水平 热心指数 信用等级 收起 理由
Tigflanker + 1 + 1 + 1 观点有启发

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

只有一个罗纳尔多

板凳
pobel 在职认证  发表于 2014-5-7 08:23:02
local的宏变量都是属于“寄生”的 ,只有所在宏被执行的时候才会存在。

而且,如果宏变量真的是”local“的话,那即便是调用这个宏,该宏变量也会随着宏执行的结束而消失。

%macro a;
  %local mvar;
  %let mvar=aaa;
%mend;

%macro b;
   %local mvar;
   %let mvar=bbb;
   %a

   %put mvar: &mvar;
%mend;

%b
已有 1 人评分学术水平 热心指数 信用等级 收起 理由
Tigflanker + 1 + 1 + 1 谢谢pobel,我更新了点东西。

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

和谐拯救危机

报纸
jeozu 发表于 2014-5-7 09:12:44
  1. %macro a;
  2.   *So many statements;
  3. %global a;  
  4. %let a = x;
  5.   *So many statements;
  6. %mend;

  7. %a;

  8. %macro b;
  9.   *How can I get the value &a. from Macro a?;
  10.   *Likes in JAVA style &a.a ;
  11. %mend;
  12. %b;
复制代码
已有 1 人评分学术水平 热心指数 信用等级 收起 理由
Tigflanker + 1 + 1 + 1 分析的有道理

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

地板
jeozu 发表于 2014-5-7 10:09:22
AML中很多rule都是用你这这方法调用的。
对于逻辑判断和循环主要是编译器方面的要求,用于判断代码执行的范围和等级。如果改动,有很多东西都需要修改。。
已有 1 人评分学术水平 热心指数 信用等级 收起 理由
Tigflanker + 1 + 1 + 1 观点有启发

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

7
Tigflanker 发表于 2014-5-7 11:00:41
pobel 发表于 2014-5-7 10:04
对于楼主的例子:
data a;
   a = %if &type. eq C %then in;put( b , best.);
是的,您说的很对。

只是我想写一个作为服务性质的宏,本来在sashelp.vmacro中找到一些线索,不过他都是仅包含global和automatic仅此两部分的值。

我当时的考虑是:当解析到%if + &type.时,直接用整段主宏预读的log窗口中抓取到type所在的:宏名,(进而获得)type的最后解析值。

最后再把这段data步解析完成。。。

其实这个想法漏洞很多,只是实在想每次调试大宏中的这某一段时,希望能够从类似大宏的“向量池”的地方找到这个值,避免将整个宏都跑一遍。
目前的做法是:在那个data步之后加一个%return;

可能的确有点牵强,不过目前是简单的%do办到了。
Bye SAS.
若有缘,能重聚。

8
Tigflanker 发表于 2014-5-7 11:04:43
jeozu 发表于 2014-5-7 10:09
AML中很多rule都是用你这这方法调用的。
对于逻辑判断和循环主要是编译器方面的要求,用于判断代码执行的范 ...
是的,当时都还是希望能有个类似宏观的option,能够主动在整个程序的最外层加个宏环境。

至少像%do这种不牵扯范围和等级的宏语句可以释放到open code中。
Bye SAS.
若有缘,能重聚。

9
yongyitian 发表于 2014-5-7 12:32:48
SAS数据步编程和宏语言有几个基本概念是与起他编程语言不同的。

1.  当今应用的最多的JAVA 和c++ 等是一种称为面向对像的语言 (object oriented programming).
一个object下面可以有多个子objects。 程序运行后生成的是一个或多个objects.
取出或调用已经生成的object内部的东西用dot方法, 如 out_obj.in_obj_1, out_obj.in_obj_2.

2.  SAS宏语言是一种文本编译与生成语言。宏运行后生成的是文本(text), 供数据步或 proc step使用。

3.  宏变量是储存在不同的 macro table 里的 。 宏运行结束后储存在local macro table里的宏变量会被清除.  除非被定义为global或上一层的宏变量。 或着%put为宏生成的text。

4.  宏语言有两种语句,一种是可以在宏内部和外部都能使用的语句,称为 open code statements,
如%let, %put, %sysfunc等. 另一种则只能在宏内部使用。%do 和 %if语句属与第二种,不能在数据步中使用。 但可以在宏内部的数据步中使用。
已有 1 人评分学术水平 热心指数 信用等级 收起 理由
Tigflanker + 1 + 1 + 1 如您所述 : - )

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

10
bobguy 发表于 2014-5-8 07:29:33
There is no way one can do it under your assumption.

A local macro variable lives within its enviroment.

Here are my recommendations,
1) pass them to an external file
2) pass them to a data set.
已有 1 人评分学术水平 热心指数 信用等级 收起 理由
Tigflanker + 1 + 1 + 1 Thank you for your guidance. :)

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

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

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2026-1-4 09:19