为什么`%str(%inner_macro())中的%str不起作用?

时间:2016-03-04 12:47:29

标签: sas sas-macro

%str应该将一个字符串作为一个参数传递给一个sas宏,即使它包含逗号,但是如果%str的参数自身是宏的结果,那么这显然不起作用?我得到ERROR: More positional parameters found than defined.

实施例

这就是错误的含义

    15         %macro outer_macro(left, right);
    16          %put NOTE: outer_macro: left is &left;
    17          %put NOTE: outer_macro: right is &right;
    18         %mend;
    19         %outer_macro(left, right);
    NOTE: outer_macro: left is left
    NOTE: outer_macro: right is right
    20         %outer_macro(left, midle, right);
    ERROR: More positional parameters found than defined.

这就是%str在正常情况下解决问题的方法。

    21         %outer_macro(left, %str(midle, right));
    NOTE: outer_macro: left is left
    NOTE: outer_macro: right is midle, right

可以使用内部宏

构造宏的参数
    23         %macro blank_macro(left, right);
    24          %put NOTE: blank_macro: left is &left;
    25          %put NOTE: blank_macro: right is &right;
    26          &left. &right.
    27         %mend;
    28         %outer_macro(links, %blank_macro(midden, rechts));
    NOTE: blank_macro: left is midden
    NOTE: blank_macro: right is rechts
    NOTE: outer_macro: left is links
    NOTE: outer_macro: right is midden rechts

但是如果内部宏插入逗号,则会得到原始错误

    30         %macro comma_macro(left, right);
    31          %put NOTE: comma_macro: left is &left;
    32          %put NOTE: comma_macro: right is &right;
    33          &left., &right.
    34         %mend;
    35         %outer_macro(left, %comma_macro(midle, right));
    NOTE: comma_macro: left is midle
    NOTE: comma_macro: right is right
    ERROR: More positional parameters found than defined.

我希望%str可以解决此问题,但事实并非如此。为什么?

    36         %outer_macro(left, %str(%comma_macro(midle, right)));
    NOTE: comma_macro: left is midle, right
    NOTE: comma_macro: right is
    ERROR: More positional parameters found than defined.

上下文

供您参考:我需要这个,因为我写了一个宏来列出我应该从数据库查询的几个字段,我需要通过另一个宏将我的sql传递给数据库。

%run_SQL(select key, %list_fields(some_arguments), from something);

2 个答案:

答案 0 :(得分:4)

您遇到的问题是%str在宏编译期间屏蔽了字符,而不是在宏执行期间。因此,宏调用适当地编译,执行%comma_macro,但是一旦执行了该值,就不再引用这些值(因为%str已经完成了它的事情)。它不会掩盖值时间。

你的%comma_macro电话也是错误的,这进一步证明了这一点。它掩盖了,,然后导致%comma_macro认为midle,right是第一个参数(如果您在宏括号内使用%str则相同)。

请注意,SAS在the %str documentation中特别提到这种做法是危险的:

  

请勿使用%STR括起其他具有参数值列表的宏函数或宏调用。   由于%STR屏蔽括号而没有匹配,因此宏处理器无法识别函数的参数或宏调用的参数值。

%quote%str相同,但masks characters during resolution除外:

  

%QUOTE和%NRQUOTE分别屏蔽与%STR和%NRSTR相同的项目。但是,%STR和%NRSTR会屏蔽常量文本而不是已解析的值。并且,%STR和%NRSTR在宏编译时起作用,而%QUOTE和%NRQUOTE在宏执行时起作用。

在您的示例中,将%str替换为%quote将非常有效。我认为%bquote可能是首选,因为它为不匹配的引号提供了额外的保护。我始终认为b中的%bquote代表better,并且从未见过使用%quote代替它的理由。

  

%BQUOTE和%NRBQUOTE函数在执行宏语言或宏语言语句期间屏蔽文本表达式的字符串或已解析值。

听起来就像你对我做的那样。您不需要使用%NRBQUOTE,除非结果中包含& %个字符。

宏报价时间表表格:

Quoting Type  | Occurs At       | Mask details
%str          | Compilation     | Unmatched Quotations/Parens with %
%nrstr        | Compilation     | Same as %str plus & %
%quote        | Execution       | Same as %str
%nrquote      | Execution       | Same as %quote plus & %
%bquote       | Execution       | Unmatched quotes/parens automatically
%nrbquote     | Execution       | Same as %bquote plus & %
%superq       | Execution       | Only variable and without &, same list as %nbrquote
 (continuned)                   | Does not attempt to resolve anything inside of variable

答案 1 :(得分:3)

引用%COMMA_MACRO

的输出
33          %macro comma_macro(left, right);
34            %put NOTE: comma_macro: left is &left;
35            %put NOTE: comma_macro: right is &right;
36            %nrbquote(&left., &right.)
37            %mend;
38         %macro outer_macro(left, right);
39            %put NOTE: outer_macro: left is &left;
40            %put NOTE: outer_macro: right is &right;
41            %mend;
42         %outer_macro(left, %comma_macro(midle, right));
NOTE: comma_macro: left is midle
NOTE: comma_macro: right is right
NOTE: outer_macro: left is left
NOTE: outer_macro: right is midle, right