I'm trying to strip some operators from a string, leaving behind variable names. I'm using the following code which doesn't work. Is there some quoting needed?
%let expression = vara / (varb + varc); %macro stripsym(string); %sysfunc(translate(&string,,+-*/())); %mend stripsym; %put Output: %stripsym(&expression); %put Desired: vara varb varc;
%let expression = vara / (varb + varc);
%macro stripsym(string);
%sysfunc(compbl(%sysfunc(translate(&string,%STR( ),+-*/()))));
%mend stripsym;
%put Output: %stripsym(&expression);
%put Desired: vara varb varc;
%STR() masks spaces in translate, COMPBL() compress multiple spaces
You post is empty. Do you have a question? Or are you trying to share something?
COMPRESS is the more natural function to remove characters.
Need some quoting function or the first ) is treated as the end of a function call.
If you want to use a the call like a function do not end the statement with a ;
This works for your example:
%let expression = vara / (varb + varc); %macro stripsym(string); %sysfunc(compress(&string,%str(+/-()))) %mend stripsym; %put Output: %stripsym(&expression);
You could replace any character not part of the SAS naming convention with a blank using the translate() function BUT.... things will become quickly complicated if your expressions also can contain functions like sum(varA,varB).
If you can limit your expressions to certain patterns then writing some code might be feasible. Something that would work for any valid SAS syntax would be very involved.
%let expression = vara / (varb + varc);
%macro stripsym(string);
%sysfunc(compbl(%sysfunc(translate(&string,%STR( ),+-*/()))));
%mend stripsym;
%put Output: %stripsym(&expression);
%put Desired: vara varb varc;
%STR() masks spaces in translate, COMPBL() compress multiple spaces
@BruceBrad wrote:
Thanks. This does what I need. I'm still puzzled by how strings get passed to translate(). Why don't I need to put quote marks around &string, but do need to use %str( ) for the space?
In normal SAS syntax (and most programming languages) you use quotes around string constants so the parser/compiler can tell the string 'DATA' from the keyword DATA or from a variable name. Or it can tell the difference between the number 100 and the string "100". But to the macro processor everything is a string. it is only looking for the macro trigger characters of & or % to know when it needs to handle things specially.
But spaces are tricky because normally extra spaces do not mean anything in SAS syntax. So without the quotes to demark the string you need some other way to tell the macro processor that you want this space to be special.
Note that another way to do the current task is to enclose both strings being passed to TRANSLATE() in quotes. That is because that would just be telling TRANSLATE() to convert the quote characters back into quote characters. Then you would not need macro quoting at all. The only trouble with that would be that you need count the number of characters correctly so that the closing quotes align with each other. Note that normally you can use a shorter target string and it will be padded with spaces.
1 %put %sysfunc(translate(ABCD,Z,ABC)); Z D
But unfortunately if you use an empty target string then it does nothing instead of translating all source characters.
2 %put %sysfunc(translate(ABCD, ,ABC)); ABCD
One solution to that is to prefix both strings with the same character (so it gets translated to itself) and then the padding of spaces will again happen.
3 %put %sysfunc(translate(A+b+c-D,A,A+-)); A b c D
When you program in 4GL you have very simple and clear difference between the code and data, code is in *.sas file, data are in SAS data set, they do not interleave between each other.
In macro programming both your code (macro language statements) and your data (4GL code) sit in one place, the *.sas file. So you have to figure out a way to tel SAS which is which. That's why there are % and & running around. If you realise this, everything is much simpler.
So now.
You don't need quotes because in the macro language there is only one variable type - text.
Everything is a text string.
%let x=123; - value of x is not one hundred and twenty three, but string build of digits 1, 2, and 3,
%let y=1+2; - value of y is not 3, it's string "1+2", and you need %SYSEVALF() to "calculate the value"
%let z=ABC; - value of z is string ABC
Since everything is a string there is no need for quotes.
If you write:
%put %sysfunc(pathname("WORK"));
you will fail, because there is no library >>"WORK"<<
But if you do:
%put %sysfunc(pathname(WORK));
everything works ok.
If you type:
%put %substr("TEST",2,1);
you will get T in the log not E as you would expect (in 4GL).
Now, for spaces.
For SAS an "empty string", or string on one space, or a string of 42 spaces is the same, both in 4GL and in macro language. The difference is that in 4GL you have quotes, which can be used to provide a single space character. In macro language
those two are the same:
%let x =;
%let y = ;
both produce and empty value for macrovariabe x and y.
So when you run:
data A&x.B;
set sashelp.class;
run;
data A&y.B;
set sashelp.class;
run;
in both cases you will get data set AB as a resutl.
So the space is a "special" character (as comma or semicolon are too) and you need to mask them in proper way. You use %STR() for that purpose (among others).
If you do:
%let x = ; /* 5 spaces */
%let y =%str( ); /* 5 spaces */
and then repeat those two data steps, the first one gives you AB the other A and B.
Bottom line. If you want to use space as a value for macrofunction (e.g., %SCAN(...)) or a function wrapped in %SYSFUNC (e.g., %sysfunc(translate(...))) you will have to "mask" it.
The best reading about masking special characters a.k.a. macroquotting is "Secrets of Macro Quoting Functions – How and Why" by Susan O’Connor, link: https://stats.oarc.ucla.edu/wp-content/uploads/2016/02/bt185.pdf
Bart
I think my confusion stems from how %sysfunc works. I was assuming that translate() was interpreted as a normal function, and following its documentation, would require quoted inputs. Is the %sysfunc(translate()) syntax best interpreted as turning translate() into a macro function, with macro-type inputs?
@BruceBrad wrote:
I think my confusion stems from how %sysfunc works. I was assuming that translate() was interpreted as a normal function, and following its documentation, would require quoted inputs. Is the %sysfunc(translate()) syntax best interpreted as turning translate() into a macro function, with macro-type inputs?
This is something that confused me as well in the beginning.
Translate() is still a SAS function and not a macro function but %sysfunc() is a macro function and that's why you don't need the quotes.
From the documentation for %SYSFUNC, %QSYSFUNC Macro Functions
function
is the name of the function to execute. This function can be a SAS function, a function written with SAS/TOOLKIT software, or a function created using the FCMP Procedure in Base SAS Procedures Guide. The function cannot be a macro function.
...
Because %SYSFUNC and %QSYSFUNC are macro functions, you do not need to enclose character values in quotation marks as you do in DATA step functions.
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
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.
Ready to level-up your skills? Choose your own adventure.