我正在编写一个宏,该宏有时会调用一些proc SQL代码。我希望用户能够指定任意proc sql选项(例如inobs = 100可能是宏的输入参数之一)。
我很难引用具有等号'='的参数。
问题之一是,我还应该检查宏参数是否为空,如果不为空,则仅将指定的选项添加到sql语句中。
以下是一个无效的示例测试,该测试不起作用并抛出
错误:宏未定义关键字参数INOBS。
我已经阅读了此内容(http://www2.sas.com/proceedings/sugi28/011-28.pdf)和其他SUGI的内容,并尝试了许多可能的方法来引用和调用宏。
如果有人可以提供以下功能的工作示例,将不胜感激。
options mprint mlogic;
data have;
length x $8;
input x;
datalines;
one
two
three
;
proc sql inobs=2;
create table sql_output as
select *
from have;
quit;
%macro pass_parameter_with_equal_sign(table=, sqlOptions=);
proc sql
%if "%left(%trim(&sqlOptions.))" ne "" %then %do;
&sqlOptions.
%end;
/* the semicolon to end the proc sql statement */
;
create table macro_output as
select *
from have;
quit;
%mend;
%pass_parameter_with_equal_sign(table=have, sqlOptions=%str(inobs=2))
title "SQL output:";
proc print data=sql_output; run;
title "Macro output:";
proc print data=macro_output; run;
啊,这实际上是您遇到的一个棘手的小问题。该问题实际上是由于致电%trim()
和引起的%left()
。
删除这些结果将使代码按预期工作(请注意,我也删除了该参数周围的宏引号):
%macro pass_parameter_with_equal_sign(table=, sqlOptions=);
proc sql
%if "&sqlOptions" ne "" %then %do;
&sqlOptions
%end;
/* the semicolon to end the proc sql statement */
;
create table macro_output as
select *
from &table;
quit;
%mend;
%pass_parameter_with_equal_sign(table=sashelp.class, sqlOptions= inobs=2);
我们可以像这样重新创建您遇到的问题:
%put %trim(inobs=1);
由于该参数解析为inobs = 1,并且%trim()
没有任何命名参数,因此抛出了嘶哑的拟合。要正确传递包含“ inobs = 1”的字符串,我们可以这样做:
%let param = inobs=1;
%put %trim(%str(¶m));
注意:Amir%if
完全删除该语句的解决方案也是设计此类代码的最佳方法。我只是提供有关您为什么遇到此问题的更多详细信息。
%left()
和%trim
不需要顶部的代码段提供与具有的原始代码相同的预期功能"%left(%trim(&sqlOptions.))"
。这是因为,除非使用宏引用明确保留了开头和结尾的空格,否则它们将从宏变量(包括宏参数)中删除。一个简单的例子来说明这一点:
%let param = lots of spaces ;
%put ***¶m***;
给出:
***lots of spaces***
您可以看到保留了内部空格,但是左侧和右侧的填充都消失了。要保留空格,我们可以简单地使用该%str()
函数。
%let param = %str( lots of spaces );
%put ***¶m***;
给出:
*** lots of spaces ***
如果实际上在宏变量上确实有空格,您需要删除该空格,因为它已被加引号,并且您想使用%left()
并%trim()
这样做,那么事情会变得有些古怪。我们的变量可以这样创建:
%let param = %str( inobs = 2 );
您可以看到我们已经用%str()引用了该值以便创建它。这意味着我们现在可以调用其中一个函数,而不必再次引用它:
%put %trim(¶m); * ALREADY QUOTED AT CREATION SO THIS WORKS FINE;
但是,如果我们随后尝试将结果输入%left()
函数中,则会回到原始问题:
%put %left(%trim(¶m)); * OOPS. DOESNT WORK;
现在我在这里猜测,但是我相信这很有可能是因为该%trim()
函数在返回结果之前会删除所有宏引用。有点像这样:
%put %unquote(%trim(¶m));
可以通过再次使用%str()重新引用返回的结果来避免这种情况:
%put %left(%str(%trim(¶m)));
...或使用%nrstr()包装原始参数:
%let param = %str( inobs = 2 );
%put %left(%trim(%nrstr(¶m)));
...或%sysfunc()
用于调用datastep函数:
%put %sysfunc(compress(¶m));
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句