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

Let's suppose I have a list of parameter names in a SAS data set, two of which are shown here

GainRange_Test Gain DCGN_L (None) 401

Image_Test UnifRMS (%rms) 114

Note that the second parameter name contains a percent sign, if I'm not careful SAS will think I am talking about the %rms macro, when in fact this is just text.

So, if I capture these parameter names in a SAS macro variable &parameters as follows:

proc sql noprint;

select distinct parameter into :parameters separated by '~' from use_these_parameters1;

quit;

%put PARAMETERS %superq(parameters);

The %put statement gives the correct result:

PARAMETERS GainRange_Test Gain DCGN_L (None) 401~Image_Test UnifRMS (%rms) 114

Now, I want to run this macro variable through a macro %eqt1 that does some useful tasks ... please note that I have stripped most of the useful tasks out of the example next just to illustrate the problem

%macro eqt1(string=);

%do ii=1 %to %sysfunc(countw(%nrbquote(&string),~));

  %let thisword=%qscan(%nrbquote(&string),&ii,~);

  %put II &ii PARAMETER "%quote(%qupcase(%nrbquote(&thisword)))";

%end;

%mend;

%eqt1(string=%superq(parameters))


Works properly (as far as I can tell), however note that in the line of the macro which begins with %put II that I have a whole lot of quoting going on. If I leave out some of this quoting, for example, if I remove the %quote function, I get a WARNING in my SASLOG

WARNING: Apparent invocation of macro RMS not resolved.

even though everything seems to work properly. The WARNING makes me nervous, but so does this extreme amount of quoting within a single command. So, my questions are:

1) Should I worry about this WARNING?

2) Is there a simpler way to do this quoting that doesn't produce the WARNING?

--
Paige Miller
1 ACCEPTED SOLUTION

Accepted Solutions
Astounding
PROC Star

Paige,

Much of the time, the warning won't hurt anything, but there are some pitfalls.  What if there actually was a macro named %RMS?  Can you guarantee that the "apparent invocations" will never actually find a macro with that name?  The other pitfall involves SASAUTOS and the autocall facility.  Once a search for a named macro fails, the automatic search process is turned off.  Additional macros would not be found, when they exist in the autocall library but have not yet been defined in the program.

I would guess this works, but haven't tested it:

%let thisword=%superq(thisword);

The %PUT statement shouldn't attempt to unquote anything.  While you have simplified your application, it is unlikely that quoting will produce any harm in subsequent code.

Good luck.

View solution in original post

6 REPLIES 6
Astounding
PROC Star

Paige,

Much of the time, the warning won't hurt anything, but there are some pitfalls.  What if there actually was a macro named %RMS?  Can you guarantee that the "apparent invocations" will never actually find a macro with that name?  The other pitfall involves SASAUTOS and the autocall facility.  Once a search for a named macro fails, the automatic search process is turned off.  Additional macros would not be found, when they exist in the autocall library but have not yet been defined in the program.

I would guess this works, but haven't tested it:

%let thisword=%superq(thisword);

The %PUT statement shouldn't attempt to unquote anything.  While you have simplified your application, it is unlikely that quoting will produce any harm in subsequent code.

Good luck.

PaigeMiller
Diamond | Level 26

Can you guarantee that the "apparent invocations" will never actually find a macro with that name?  The other pitfall involves SASAUTOS and the autocall facility.

Today, I can state that there are no %rms macros available to the system. I cannot state that this will always be true in the future, nor can I anticipate possible future parameter names that might contain other text strings beginning with a percent sign. Thus, my desire to make sure the code always avoids trying to use %rms (or %whatever) in the parameter names as a macro invocation.

I would guess this works, but haven't tested it:

%let thisword=%superq(thisword);

Hmmm ... appears to work as you stated, I remove all the quoting from the %put statement except I still need %qupcase, and it works.

So, I don't know if there's a simple explanation why this works, I will attempt to figure this out, but if you can explain in one paragraph why this works, it would be greatly appreciated.

And why doesn't %NRBQUOTE work here? It seems to me that from my reading of the docs about %NRBQUOTE, it should do what I want as well, but it does not.

--
Paige Miller
Astounding
PROC Star

Best guess:  %nrbquote needs to resolve &STRING.  As part of that resolution, it keeps re-resolving until all macro triggers (& and %) are gone.  Once that happens, %nrbquote works on the resulting string.

The attempted invocation of %rms occurs when resolving &string, before %nrbquote starts quoting.

data_null__
Jade | Level 19

Are the strings data or code.  I you can keep them out of the code (macro world) then no problem.  Maybe easier said than done.

Tom
Super User Tom
Super User

I would put the call to %SUPERQ() right after the SQL code that creates the string.

data have ;

input parameter $50. ;

cards4;

GainRange_Test Gain DCGN_L (None) 401

What about, comma?

Image_Test UnifRMS (%rms) 114

;;;;

proc sql noprint;

select distinct parameter into :parameters separated by '~' from have;

%let parameters=%superq(parameters);

quit;

%macro eqt1(string=);

%do ii=1 %to %sysfunc(countw(&string,~));

  %let thisword=%qscan(&string,&ii,~);

  %let upword = %qupcase(&thisword);

  %put II=&ii PARAMETER=|&upword|;

%end;

%mend;


%eqt1(string=&parameters);

PaigeMiller
Diamond | Level 26

Thanks, everyone.

I had a feeling there were much simpler ways to get this done, I just have to get to the point where these concepts are much clearer in my mind.

--
Paige Miller

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

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
  • 6 replies
  • 925 views
  • 3 likes
  • 4 in conversation