问题
%str should pass a string as one parameter to a sas macro, even if it contains commas, but that apparently does not work if the argument of %str is in it self the result of a macro? I get ERROR: More positional parameters found than defined.
Example
This is what the error means
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.
This is how %str
resolves it in normal situations.
21 %outer_macro(left, %str(midle, right));
NOTE: outer_macro: left is left
NOTE: outer_macro: right is midle, right
It is possible to construct an argument of a macro with an inner macro
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
But if the inner macro inserts a comma, you get the original error
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.
I would expect %str
to resolve this, but it does not. Why?
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.
Context
For your information: I need this because I wrote a macro to list a few fields I should query from a database and I need to pass my sql to the database via another macro.
%run_SQL(select key, %list_fields(some_arguments), from something);
回答1:
Quote the output from %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
回答2:
The problem you have is that %str
masks characters during macro compilation, not during macro execution. So, the macro call compiles appropriately, executes %comma_macro
, but then once that's executed, the values are no longer quoted (as %str
has already done its thing). It won't mask the values a second time.
That's evidenced further by the fact that your %comma_macro
call is also wrong. It masks the ,
, which then leads to %comma_macro
thinking midle,right
is the first argument (identically to if you'd used the %str
inside the macro parentheses).
Note that SAS specifically mentions this practice as dangerous in the %str documentation:
Do not use %STR to enclose other macro functions or macro invocations that have a list of parameter values. Because %STR masks parentheses without a match, the macro processor does not recognize the arguments of a function or the parameter values of a macro invocation.
%quote
is identical to %str
, except it masks characters during resolution:
%QUOTE and %NRQUOTE mask the same items as %STR and %NRSTR, respectively. However, %STR and %NRSTR mask constant text instead of a resolved value. And, %STR and %NRSTR work when a macro compiles, while %QUOTE and %NRQUOTE work when a macro executes.
In your example, replacing %str
with %quote
would work perfectly well. I would argue %bquote is probably the preferred choice, however, as it provides additional protection for unmatched quotation marks. I've always assumed the b
in %bquote
stood for better
, and never seen a reason to use %quote
over it.
The %BQUOTE and %NRBQUOTE functions mask a character string or resolved value of a text expression during execution of a macro or macro language statement.
That sounds like what you're doing to me. You don't need to use %NRBQUOTE
, unless & %
characters might be in the result.
The table of macro quoting timelines:
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
来源:https://stackoverflow.com/questions/35796489/why-does-the-str-in-strinner-macro-not-work