Sas 为什么“%str(%internal_macro())`中的%str不起作用?

Sas 为什么“%str(%internal_macro())`中的%str不起作用?,sas,sas-macro,Sas,Sas Macro,%str应该将字符串作为一个参数传递给sas宏,即使它包含逗号,但如果%str的参数本身是宏的结果,则显然不起作用?我发现错误:找到的位置参数比定义的多。 例子 这就是错误的意思 15 %macro outer_macro(left, right); 16 %put NOTE: outer_macro: left is &left; 17 %put NOTE: outer_macro: right is &

%str应该将字符串作为一个参数传递给sas宏,即使它包含逗号,但如果%str的参数本身是宏的结果,则显然不起作用?我发现
错误:找到的位置参数比定义的多。

例子 这就是错误的意思

    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);

引用%COMMA\u宏的输出

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

您遇到的问题是,
%str
在宏编译期间屏蔽字符,而不是在宏执行期间屏蔽字符。因此,宏调用会进行适当的编译,执行
%comma\u macro
,但一旦执行,值就不再被引用(因为
%str
已经完成了它的工作)。它不会再次屏蔽这些值

您的
%comma\u宏
调用也是错误的,这进一步证明了这一点。它屏蔽了
,然后导致
%comma_macro
认为
midle,right
是第一个参数(与在宏括号内使用
%str
相同)

请注意,SAS在以下情况中特别提到这种做法是危险的:

不要使用%STR来封装具有参数值列表的其他宏函数或宏调用。 由于%STR屏蔽了不匹配的括号,因此宏处理器无法识别函数的参数或宏调用的参数值

%quote
%str
相同,不同之处在于:

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

在您的示例中,将
%str
替换为
%quote
将非常有效。然而,我认为这可能是首选,因为它为不匹配的引号提供了额外的保护。我一直认为
%bquote
中的
b
代表
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

或%outer_宏(左,%nrbquote(%comma_宏(中,右));当%逗号_宏不引用结果时。也许昆廷会来解释这一切。我认为官方说法是%BQUOTE中的B代表“blind”,比如“引用解析这个宏表达式时得到的任何值,尽管我在代码中看不到该值。”而不是%STR/%NRSTR,它引用了你可以看到的符号。同意,%BQUOTE替换了%QUOTE。我从未发现%NRBQUOTE有用,因为它实际上并不阻止宏处理器尝试解析%or&。我认为%SUPERQ()做了%NRBQUOTE应该做的事情。我相信Whitlock大师已经写过%STR%NRSTR%BQUOTE%SUPERQ是一套完整的引用函数,应该足够了。
%QUOTE/%BQUOTE
两者都有这一功能-它们都是执行时,而不是编译时。这很可能意味着失明,但在我的脑海里,我总是想得更好:)而且——我同意伊恩的观点,尽管我至少遇到过一个边缘案例,我想要的是什么;我不记得那是什么了,说得对。可能不知道是否有不匹配的引号Bquote可以处理这些%Quote无法处理的问题(除非标记)。但是,我同意,%Bquote肯定更好,而且是在%quote之后。所以也许他们不得不给它起个新名字。如果%NRBQUOTE有用且不会生成失败解析警告,您肯定会感兴趣。