4

I have a requirement to read the string with both single quotes and without quotes from a macro retrieve_context.

While calling the macro, users can call it with either single quotes or without quotes, like below:

%retrieve_context('american%s choice', work.phone_conv, '01OCT2015'd, '12OCT2015'd)
%retrieve_context(american%s choice, work.phone_conv, '01OCT2015'd, '12OCT2015'd)

How to read the first parameter in the macro without a single quote?

I tried %conv_quote = unquote(%str(&conv_quote)) but it did not work.

moodymudskipper
  • 46,417
  • 11
  • 121
  • 167
Naga Vemprala
  • 718
  • 3
  • 16
  • 38
  • It is hard to tell what you are actually asking, but you probably want the DEQUOTE() function. – Tom Oct 12 '15 at 21:57

2 Answers2

5

You're running into one of those differences between macros and data step language.

In macros, there is a concept of "quoting", hence the %unquote macro function. This doesn't refer to traditional " or ' characters, though; macro quoting is a separate thing, with not really any quote characters [there are some sort-of-characters that are used in some contexts in this regard, but they're more like placeholders]. They come from functions like %str, %nrstr, and %quote, which tokenize certain things in a macro variable so that they don't get parsed before they're intended to be.

In most contexts, though, the macro language doesn't really pay attention to ' and " characters, except to identify a quoted string in certain parsing contexts where it's necessary to do so to make things work logically. Hence, %unquote doesn't do anything about quotation marks; they are simply treated as regular characters.

You need to, instead, call a data step function to remove them (or some other things, but all of them are more complicated, like using various combinations of %substr and %index). This is done using %sysfunc, like so:

%let newvar = %sysfunc(dequote(oldvar));

Dequote() is the data step function which performs largely the same function as %unquote, but for normal quotation characters (", '). Depending on your ultimate usage, you may need to do more than this; Tom covers several of these possibilities.

Joe
  • 62,789
  • 6
  • 49
  • 67
  • Good answer but I think that saying dequote is similar to unquote is kind of misleading. I'd consider changing that just in case people take it too literally. – Robert Penridge Oct 14 '15 at 20:10
  • @RobertPenridge How's it misleading? They do more or less the same thing, don't they - except that `%unquote` removes macro 'quotations', which are not " characters but conceptual things. In both cases they remove them. Hopefully the rest of the answer makes that difference clear? – Joe Oct 14 '15 at 20:11
  • I think for people experienced with macro quoting it's fine, but they're not the ones that will be benefiting from your answer. For a contrived example consider `dequote("'this','string'")` vs `"%unquote(%str(this),%str(string)"`. I'm sure I could come up with a bunch of other examples where they behave differently. How about nested macro quotes? How about `%let x = in %str(the) middle;`. The %unquote is working it's magic in the middle of the string, not removing quotes from the outside... idk... – Robert Penridge Oct 14 '15 at 20:17
3

If the users are supplying your macro with a value that may or may not include outer quotes then you can use the DEQUOTE() function to remove the quotes and then add them back where you need them. So if your macro is defined as having these parameters:

%macro retrieve_context(name,indata,start,stop);

Then if you want to use the value of NAME in a data step you could use:

name = dequote(symget('name'));

If you wanted to use the value to generate a WHERE clause then you could use the %SYSFUNC() macro function to call the DEQUOTE() function. So something like this:

where name = %sysfunc(quote(%qsysfunc(dequote(%superq(name)))))

If your users are literally passing in strings with % in place of single quotes then the first thing you should probably do is to replace the percents with single quotes. But make sure to keep the result macro quoted or else you might end up with unbalanced quotes.

%let name=%qsysfunc(translate(&name,"'","%"));
Tom
  • 47,574
  • 2
  • 16
  • 29
  • There is no need to macro quote the arguments in that call. The value of NAME must have been quoted when the macro was called. The string `"'"` does not need macro quoting and neither does the string `"%"` since the percent is followed immediately by a double quote. Translate will convert the percent to single quote and the double quotes to double quotes. It doesn't really matter that it has the double quotes twice. It doesn't matter whether it matches the first or second one since both are translated to double quotes. – Tom Oct 12 '15 at 22:18
  • The double quote characters make it so you do not need to worry about macro quoting the single quote or the percent. – Tom Oct 12 '15 at 22:22
  • Oh, I think I see: you're avoiding the problems having a hanging ` or % around. Understood, thanks! I didn't think about the side effect of the quotations there. – Joe Oct 12 '15 at 22:22
  • Thank you @Joe and Tom .. It was a great learning today because of you :) – Naga Vemprala Oct 12 '15 at 22:38