SAS宏执行顺序
我使用宏锁定数据集:SAS宏执行顺序,sas,sas-macro,Sas,Sas Macro,我使用宏锁定数据集: %macro lockTab(member=APP_DATABASE,timeout=30,retry=500); %global LOCK_&member; %let LOCK_&member = ; %local starttime; %let starttime = %sysfunc(datetime()); %put try to lock &member.: &starttime; %do %until (&
%macro lockTab(member=APP_DATABASE,timeout=30,retry=500);
%global LOCK_&member;
%let LOCK_&member = ;
%local starttime;
%let starttime = %sysfunc(datetime());
%put try to lock &member.: &starttime;
%do %until (&syslckrc = 0
or %sysevalf(%sysfunc(datetime()) > (&starttime + &timeout)));
lock APPLIB.&member.;
%put syslckrc=&syslckrc;
%if &syslckrc > 0 %then %let rc=%sysfunc(sleep(&retry.));
%end;
%let endtime = %sysfunc(datetime());
%put end of try to lock &member.: &endtime;
%if &syslckrc <= 0 %then %do;
%let LOCK_&member = LOCK;
%end;
%else %do;
%let _appRetcode = 12;
%let _appErrtext = Database is locked.;
%end;
%put ende Locktab: appretcode: &_appRetcode;
%put ende Locktab: syslckrc: &syslckrc;
%mend;
这是我的日志:
NOTE: 1 record was written to the file _WEBOUT.
The minimum record length was 42.
The maximum record length was 42.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
SYMBOLGEN: Macro variable _APPRETCODE resolves to 0
EYECATCHER 0
SYMBOLGEN: Macro variable MEMBER resolves to APP_DATABASE
SYMBOLGEN: Macro variable MEMBER resolves to APP_DATABASE
SYMBOLGEN: Macro variable MEMBER resolves to APP_DATABASE
The SAS System
SYMBOLGEN: Macro variable STARTTIME resolves to 1834989255.00056
try to lock APP_DATABASE: 1834989255.00056
SYMBOLGEN: Macro variable MEMBER resolves to APP_DATABASE
ERROR: A lock is not available for APPLIB.APP_DATABASE.DATA.
ERROR: Lock held by process 1360575.
SYMBOLGEN: Macro variable SYSLCKRC resolves to 70031
syslckrc=70031
SYMBOLGEN: Macro variable SYSLCKRC resolves to 70031
SYMBOLGEN: Macro variable RETRY resolves to 500
SYMBOLGEN: Macro variable SYSLCKRC resolves to 70031
SYMBOLGEN: Macro variable STARTTIME resolves to 1834989255.00056
SYMBOLGEN: Macro variable TIMEOUT resolves to 30
SYMBOLGEN: Macro variable MEMBER resolves to APP_DATABASE
ERROR: A lock is not available for APPLIB.APP_DATABASE.DATA.
ERROR: Lock held by process 1360575.
.......
end of try to lock APP_DATABASE: 1834989285.01467
SYMBOLGEN: Macro variable SYSLCKRC resolves to 70031
SYMBOLGEN: Macro variable _APPRETCODE resolves to 12
ende Locktab: appretcode: 12
The SAS System
SYMBOLGEN: Macro variable SYSLCKRC resolves to 70031
ende Locktab: syslckrc: 70031
为什么EYECATCHER在我的宏输出之前打印出来
我希望首先输出宏lockTab,然后是“eyecatcher12”。
""
%调试给出:(范围/变量/值)全局/_APPRETCODE/12只是一个想法:
你试过在宏调用后加分号吗?缺少分号通常会带来一些问题。即使宏看起来运行正常。您提供的代码是否包装在父宏中 我能够重现这种行为,但只能在另一个宏中重现 示例代码:
%macro x;
%macro demo1(); %put see; %mend;
%macro demo2(); %put this; %mend;
%demo1 %put here; %demo2()
%mend;
%x
其中打印:
here
see
this
see
here
this
与之形成对比的是:
%macro demo1(); %put see; %mend;
%macro demo2(); %put this; %mend;
%demo1 %put here; %demo2()
其中打印:
here
see
this
see
here
this
这确实似乎是一个解析器错误,或者至少是一个不一致性
我建议将子宏定义移到父包装器之外。我还建议始终使用括号定义宏,并按括号调用宏。我认为问题与解析器决定宏调用何时结束有关。如果宏是用参数定义的(即使参数列表为空),则宏调用不会在空白处结束。它以右括号结束。它还将在SAS语言标记(包括SAS语言分号)或另一个宏调用处结束 这就是为什么像下面这样丑陋的东西会起作用:
%macro doit (x=) ;
%put &=x ;
%mend doit;
%doit (x=3)
改变@Allan的示例,如果demo1和demo2的定义没有参数,那么代码会工作,因为demo1和demo3的调用将由空格触发
358 %macro demo1; %put 1 first; %mend;
359 %macro demo3; %put 3 third; %mend;
360 %macro x;
361 %demo1
362 %put 2 second;
363 %demo3
364 %mend x;
365 %x
1 first
2 second
3 third
但是,如果使用参数列表定义了%demo1,则空格不足以结束宏调用。即使是%PUT语句也不会结束宏调用。SAS一直在寻找参数列表,直到它命中调用%demo3,并意识到“好吧,必须完成第一个宏调用。”此时%PUT语句已经执行
366 %macro demo1(); %put 1 first; %mend;
367 %macro demo3; %put 3 third; %mend;
368 %macro x;
369 %demo1
370 %put 2 second;
371 %demo3
372 %mend x;
373 %x
2 second
1 first
3 third
作为证据,请考虑如下。看起来我正在将VAR参数传递给%X(它没有定义参数)。但是%demo1的调用仍然在愉快地等待参数列表,并且它接受了它。这表明%PUT语句不足以结束对%demo1的调用
404 %macro demo1(var=); %put 1 first; %put &=var ;%mend;
405 %macro x;
406 %demo1
407 %put 2 second;
408 %mend x;
409 %x(var=hello)
2 second
1 first
VAR=hello
我很难记住伊恩·惠特洛克教给我的所有规则,有时我害怕把一条我记错了的规则归咎于他。但我很有信心,他认为所有宏都应该至少有一个参数(他对宏的定义是“参数化的代码单元”),并且宏调用应该总是以括号结束,即使它是接受默认值的空参数列表,即%doit()。这确保了宏在预期的情况下执行,而不添加SAS语言分号,这有时会把事情搞砸。我被告知在调用宏时不要使用分号。如果我调用“%lockTab()”而不是“%lockTab”,它会工作。所以它看起来和括号有关。但是为什么呢?解析器错误?好的,那么您是通过在宏调用之后添加括号来实现的,就像这样
%lockTab()
?不知道为什么会这样。但如果你能让它工作,那就太好了!在宏调用之后包含分号肯定不是一个好的做法,因为它们可能会导致错误。考虑:%macro x();y=x;%修理数据;如果为0,则为%x();否则1=1;运行
将由于if-else逻辑过早终止而导致错误。@AllanBowe很好,您已经指出了这一点。在过去的10年里,我经常使用宏,从未遇到过由此引起的错误。您提供的示例是有效的,但我在实践中从未遇到过这样的用例。