BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
weg
Obsidian | Level 7 weg
Obsidian | Level 7

 

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:

MLOGIC(PROCESSARRAY): %PUT &=HNAME
WARNING: Apparent symbolic reference HNAME not resolved.
HNAME
MLOGIC(PROCESSARRAY): %PUT &=_cstring
WARNING: Apparent symbolic reference _CSTRING not resolved
 

 

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!

 

1 ACCEPTED SOLUTION

Accepted Solutions
Patrick
Opal | Level 21

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

 

View solution in original post

4 REPLIES 4
Patrick
Opal | Level 21

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

 

weg
Obsidian | Level 7 weg
Obsidian | Level 7

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.

 

Patrick
Opal | Level 21

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

 

Tom
Super User Tom
Super User

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;

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 4 replies
  • 676 views
  • 2 likes
  • 3 in conversation