BookmarkSubscribeRSS Feed

Demystifying Macro Masking Functions Q&A, Slides, and On-Demand Recording

Started 2 weeks ago by
Modified 2 weeks ago by
Views 288

Watch this Ask the Expert session to explore the most commonly used masking functions of the SAS macro language.

 

Watch the Webinar

 

You will learn to use masking functions for special characters like:

  • Ampersand (Smith & Sons).
  • Apostrophe (Mary’s Market).
  • Comma (as a macro function argument). 

 

The questions from the Q&A segment held at the end of the webinar are listed below and the slides from the webinar are attached.

 

Questions & Answers

Will this work in Enterprise Guide when Enterprise Guide inserts &, <, and >?

Answer:

As far as I know, all macro code and functions work equally on Enterprise Guide, SAS Studio, and Windows.

 

In the name macro example, could you put the comma in quotes for the %scan function? You used the %str function instead.

Answer:

Yes, that would work as well.   But it won’t work in all cases, because the quotation mark may become an unwanted part of the macro value.   For example:  %let clear=”title;footnote;”; is not the same as %str(title;footnote;);

 

If you did not explicitly list the comma as a delimiter, would the value of last be "Taylor," when the entry is "Taylor, Jenna"?

Answer:

It would still be Jenna Tayor, because omitting the 3rd argument in the SCAN function then invokes all the default delimiters, eg -,_+, …etc

 

When I run or debug SAS code that uses macro variables or macro functions, SAS sometimes reports errors such as unmatched quotation marks. I then have to close and restart SAS to fix it. Is there a way to clear all macro errors and continue using the same SAS session?

Answer:

If I accidently omitted a closing quote (a common issue) I’d add an additional line,  something like:

 

 *’; %put looks good now;

 

 If the *’ did the job, you’d see the message “looks good now” in your SAS log.   The purpose of the * preceeding the ‘ is to act as a comment, so as not to introduce a hanging quote where none previously existed.

 

For the %name(Taylor, Jenna) case, can this be resolved by calling %name(Taylor%, Jenna)?

Answer:

Likely note, since the % alone won’t mask anything.   It’s actually used a comment inside a macro definition.

 

Are there any situations where you would want to use %scan instead of %qscan?

Answer:

Most of the time I don’t want ambiguous characters to be returned from a macro variable resolution.  But, yes, if you know you want or don’t care if a macro variable’s value were returned un-masked, %scan would do that.  In our example below, the parameter FULLNAME is returned with a comma which caused the macro definition to *think* there were two parameters on the %macro statement.  But if we submitted the %name macro call statement below, the %scan would be fine.

%macro name(fullname);
  %let first=%scan(&fullname,2);
  %let last= %scan(&fullname,1,%str( ));
  %let newname =&first &last;
  %put &newname;
%mend;

%name(%str(James-Scott, Walter))

How do macro masking functions control whether macro triggers such as & and % are interpreted as triggers or treated as plain text?

Answer:

Both will always be treated as macro triggers unless quoted.  What’s more, when encountered in SAS code, these macro triggers will always execute while the remainder of your non-macro code is still being compiled.  For example, the code below will fail the first execution, then without making any modifications, will “miraculously” work the 2nd time because &howmany will have been populated on the first run.  This is one of the most important lessons to be learned by new macro programmers.

data _null_;
set sashelp.class end=last;
  classcount + 1;
  if last then call symputx('howmany',classcount);
      %put The class has &howmany students; /*this statement will execute first*/
 run; 

Can a compile‑time macro function still work during the execution phase? Once code is compiled, is the masking effect lost during execution?

Answer:

  1. Yes, I’ve seen some examples where %str seems to protect resolved text; I don’t under why … but I recommend using %superq or %bquote so there’s no question or ambiguity.
  2. With a compile time macro function (%str) the masking is released when the macro variable is resolved.
  3. With execution time macro functions (%superq) the masking is released when the protected value exits the macro facility, as it’s no longer needed. 
  4. An exception we saw in class was the %bquote function where the masking stays in place until explicitly released with the %unquote function.
  5. Is this confusing?  Yes!   General rule:   When text leave the macro processor, the protective masking is removed.

Can I use %str("&cust1", "&cust2")?

Answer:

Yes, you can, but remember all the %str does here is (as I said in class) “removes the normal syntactical significance of the quotes.”  That means they’ll still be treated as text, but not recognized as true quotes;

%macro test(cust1);
 %if %str("&cust1") = Joe %then
     %put this is &cust1;
	 %else %put this is not Joe;
%mend;
%test(Joe)
this is not Joe

In demo 3.3, could the TITLE issue be solved by adding a period, for example:

title "customers: &list.";

Answer:

I don’t think so, because we’ll still have the issue of two back-to-back double quotes.  That said, there are other tricks we could have tried, but my goal was to just illustrate the fact that the Execution time function %bquote needs to be unquoted with %unquote.   I admit it was clumsy, but it did illustrate my point.

 

Why do you not need & before list in the final example that uses %superq?

Answer:

I don’t really know why …. Good question.   I’ve just accepted this as a code developer’s whim.

 

How can macro masking functions be used to correctly handle special characters such as ampersands, apostrophes, and commas to prevent errors during macro execution?

Answer:

%superq permits macro resolution only ONCE, but then protects the results of this resolution and blocking any further resolution in this string … including all special tokens (*,;+=# along with all the comparison operators GE IN OR, etc) and is considered the gold standard.  Here’s an example:

data _null_;
   call symputx('rich','Ask&theexpert');
run;

Notice, that without %superq protection, macro tries to resolve the macro variable &theexpert.

%put &=rich; 
LOG:  WARNING: Apparent symbolic reference THEEXPERT not resolved.

Now, with superq, that subsequent symbolic resolution does not occur.
%put %superq(rich);

LOG: %put %superq(rich);
Ask&theexpert

 

Recommended Resources

SAS Macro Language 1: Essentials

SAS Macro Language 2: Advanced Techniques

Please see additional resources in the attached slide deck.

 

Want more tips? Be sure to subscribe to the Ask the Expert board to receive follow up Q&A, slides and recordings from other SAS Ask the Expert webinars.

Comments
Tom

Thanks.

Minor typo on page 9 of the PDF file.

Macro variable names often contain special characters, ...

I assume you meant say variable VALUES instead of variable NAMES.  Macro variable names could never contain any special characters because they follow normal SAS naming conventions.

 

And this question in the Q&A is simple if you just take a minute to think about it.

Why do you not need & before list in the final example that uses %superq?

Answer:

I don’t really know why …. Good question.   I’ve just accepted this as a code developer’s whim.

If you added an & then that would mean you want to pass the VALUE of the macro variable to %SUPERQ().  But SUPERQ wants the NAME of the macro variable.  If you tried to pass the value and it contains one of the special characters then you would need to pre-quote the value before %SUPERQ() could see.  And if you did want to quote the value you could just use %BQUOTE().

 

Where you might use & when calling %SUPERQ() is when you want to generate the NAME at execution time.    So perhaps you have a macro variable with the name of another macro variable.  This code will add macro quoting to the value of the NAME1 macro variable.

%let myvar=name1;
%let &myvar = %superq(&myvar);

Or perhaps you have series a macro variables with the same basename and different suffixes.

data _null_;
  set sashelp.class;
  call symputx(cats('name',_n_),name);
run;
%let basename=name;
%let suffix=1;
%let &basename.&suffix = %superq(&basename.&suffix);

 

Contributors
Version history
Last update:
2 weeks ago
Updated by:

Catch up on SAS Innovate 2026

Nearly 200 sessions are now available on demand with the SAS Innovate Digital Pass.

Explore Now →

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Article Tags