I am trying to take an array as input to my macro, along with the variables that go into each array dimension. To perform my processing, I need to split the input into the array name and the variable defining each dimension. The relevant portion of code I am having trouble with is:
%macro ProcessArray(in_array= );
%let text_array= "&in_array";
%let _re = %SYSFUNC(prxparse("!(.+)\((.+)\)!"));
%let match = %SYSFUNC(prxmatch(&_re, &text_array));
%put &match;
%if &match %then
%do;
/* name of array */
%let HNAME = %SYSFUNC(prxposn(&_re, 1, &text_array)); *might need to use VVALUEX;
/* comma separated classifiers*/
%let _cstring = %SYSFUNC(prxposn(&_re, 2, &text_array));
%end;
%else %put "ERROR: regex failed match to function input";
%put &=HNAME;
%put &=_cstring;
%mend;
data test();
%ProcessArray(in_array=HARRAY(classifier1,classifier2,classifier3, classifier4, classifier5));
/* put "NOTE: &ndims"; */
run;
error message:
However the same code not done in the macro step works fine:
%macro ProcessArray(in_array = ); /* Separating array input and arrayname */ _text="&in_array"; _re = prxparse("/(.+)\((.+)\)/"); if prxmatch(_re, _text) then do; /* name of array */ HNAME = prxposn(_re, 1, _text); *might need to use VVALUEX; /* comma separated classifiers*/ _cstring = prxposn(_re, 2, _text); end; else put "ERROR: regex failed match to function input"; put "NOTE: " HNAME=; put "NOTE: " _cstring=;
%mend;
The output I want to see is HNAME=HARRAY, _cstring= classifier1,classifier2,classifier3, classifier4, classifier5
Thanks!
You need macro quoting.
%let _cstring=classifier1,classifier2,classifier3, classifier4, classifier5;
%let delimiter = ,;
%let i=2;
%let parse=%scan(%nrbquote(&_cstring),&i,%nrbquote(&delimiter));
%put &=parse;
PARSE=classifier2
Remove the quotes.
%sysfunc() lifts SAS functions on macro level and macro language is purely text based so you don't need to quote strings.
%macro ProcessArray(in_array= );
%let text_array= &in_array;
%let _re = %SYSFUNC(prxparse(/(.+)\((.+)\)/));
%let match = %SYSFUNC(prxmatch(&_re, &text_array));
%put &match;
%if &match %then
%do;
/* name of array */
%let HNAME = %SYSFUNC(prxposn(&_re, 1, &text_array));
*might need to use VVALUEX;
/* comma separated classifiers*/
%let _cstring = %SYSFUNC(prxposn(&_re, 2, &text_array));
%end;
%else %put "ERROR: regex failed match to function input";
%put &=HNAME;
%put &=_cstring;
%mend;
data test();
%ProcessArray(in_array=HARRAY(classifier1,classifier2,classifier3, classifier4, classifier5));
/* put "NOTE: &ndims"; */
run;
HNAME=HARRAY _CSTRING=classifier1,classifier2,classifier3, classifier4, classifier5
Wow I cant believe I didnt get that. I had another portion of my code throwing an error that made me not catch it, and its the same problem so I was wondering how I would fix it. The non macro part that iterates through the _cstring
do i=1 by 1 until (parse = ' '); parse = scan(_cstring, i, ',')
end;
I'm assuming I need to get rid of the quotes, so I figured I should turn it into something like this:
%let delimiter = ,;
%let i = 0;
%do %until (%length(&parse) = 0); %let i = %eval (&i +1); %let parse = %SYSFUNC(SCAN(&_cstring, &i, &delimiter));
%end;
but then I get
ERROR: The function SCAN referenced by the %SYSFUNC or %QSYSFUNC macro function has too many arguments.
so I'm assuming its the &delimiter portion that is messed up? how do you get around not being able to use quotes in %sysfunc? I know %scan exists but it has the same error message.
You need macro quoting.
%let _cstring=classifier1,classifier2,classifier3, classifier4, classifier5;
%let delimiter = ,;
%let i=2;
%let parse=%scan(%nrbquote(&_cstring),&i,%nrbquote(&delimiter));
%put &=parse;
PARSE=classifier2
You need macro quoting,
%let string=A,B,C;
%let dlm= ,;
%do i=1 %to %sysfunc(countw(%str(&string),%str(&dlm)));
%let word=%scan(%str(&string),%str(&dlm));
%put &=i &=word;
%end;
or better planning. It does not make any sense to use comma as the delimiter. Space is a better delimiter if you are going to use the string to generate commands. For example if STRING is list of variable names.
But otherwise just use some other character that is not in the data and is not critical to writing code.
%let string=A|B|C;
%let dlm= |;
%do i=1 %to %sysfunc(countw(&string,&dlm));
%let word=%scan(&string,&dlm);
%put &=i &=word;
%end;
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.