SAS MACRO 引用问题:将带有宏触发器的字符串作为宏参数传递

SAS MACRO Quoting issue : passing string with macro trigger as macro parameter

是否可以将带有宏触发器的字符串作为宏参数传递? 请参阅下面的示例代码:

options mprint;
%let string5='%abc%def%';
%macro test(string);
data _null_;
    call execute('%test2('||&string.||')');
run;
%mend;

%macro test2(string2);
    data test3;
        a=%str(%')&string2.%str(%');
    run;
%mend;

%test(&string5);

此代码 运行 成功,但它试图调用宏 %abc 和 %def,这导致了警告。

如果我试图将其放入引号中以屏蔽字符串,则会出现语法错误,如下所示:

options mprint;

    %let string5='%abc%def%';
    %macro test(string);

    data _null_;
        call execute('%test2('||%superQ(string)||')');
    run;
    %mend;

    %macro test2(string2);
        data test3;
            a=%str(%')&string2.%str(%');
        run;
    %mend;

    %test(&string5);

ERROR 22-322: Syntax error, expecting one of the following: a name, a quoted string, a numeric constant, a datetime constant, a missing value, arrayname, (, +, -, INPUT, NOT, PUT, ^, _NEW_, ~.  

有没有办法在没有警告的情况下解决这个问题? 提前致谢!

如果这已经按照你想要的方式工作,而你只是想抑制这条警告消息,你可以考虑在 运行 有问题的代码部分之前设置 option nomerror;,然后设置之后又回来了。

在宏中通常很简单,可以防止特殊字符。例如,您可以使用 %superq() 函数来引用现有的宏变量值。

where name like %unquote(%str(%')%superq(parm1)%str(%'))

或者在数据步骤中使用symget()函数来获取值,根本不需要展开宏。

pattern = quote(symget('parm1'),"'");

但困难的部分是进行宏调用。您需要保护字符才能获得对 运行 的宏调用。您可以在宏调用中使用类似的功能。

一个有用的做法是指示用户将参数值作为带引号的字符串传递,然后宏代码可以在不需要时删除引号。

%macro mymacro(parm1=);
  %let parm1=%qsysfunc(dequote(&parm1));
  ...
%mend;
%mymacro(parm1='fred%')

或者您可以要求他们按名称传递值。

%macro mymacro(mvar=);
  %local pattern ;
  %let pattern=%superq(&mvar);
  ...
%mend ;

%let my_pattern=%qsysfunc(dequote('fred%'));
%mymacro(mvar=my_pattern)

试试这个:

%let string5='%abc%def%';
%macro test(string);
data _null_;
    call execute('%test2('||%nrstr("&string.")||')');
run;
%mend;

%macro test2(string2);
    data test3;
        a=%nrquote(&string2.);
    run;
%mend;

%test(&string5);

只是更新我选择的最终解决方案。我放弃了在不同宏之间传递宏参数的方式,而是将宏变量名作为字符串传递。示例代码如下:

options mprint;
%let string5='%abc%def%';

%macro test(string);
data _null_;
    call execute('%test2('||&string.||')');
run;
%mend;

%macro test2(string2);
    data test3;
        a=&&&string2.;
    run;
%mend;

%test('string5');