In the following program, parameter_2 is resolving with trailing spaces for each source value from the macro variable. Here the idea is I want to remove the special character before the first word and after the last word in the value of the macro variable and I want to separate each value with tilde operator and also ensclose each value with double quotes.
%let parameter_2=Medical Insurance,Left Atrial Appendage (LAA); data have; length target $32767; source = "¶meter_2."; do i = 1 to countw(source,","); word = scan(source,i,","); put word $hex50.; * increase format width if needed; * later, add use of COMPRESS to get rid of unwanted special characters; target = catx("~",target,quote(compress(word,'0D0A'x))); end; call symputx('parameter_2',target,'g'); run; %put ####parameter_2 is: ¶meter_2.;
Log:
94 %put ####parameter_2 is: ¶meter_2.; ####parameter_2 is: "Medical Insurance "~"Left Atrial Appendage (LAA) "
Desired Result:
####parameter_2 is: "Medical Insurance"~"Left Atrial Appendage Closure (LAA)"
1) First and foremost!
If you have a "user input" in a macrovariable NEVER(!) call it by ¯ovariable.
Always user SYMGET() function!
What if macrovariable value is: "; run; x 'format C:\';;
?
The symget() will push the value directly into a text variable without any risk and the & will "blow up" the system...
2) Do it like this:
/* input: */
%let Parameter_2 = "Medical Insurance"~"Left Atrial Appendage (LAA)";
/* process: */
data _null_;
length p $ 32767;
p=symget('Parameter_2');
t=p; /* to get P's length */
n=countw(t,"~","Q");
t='';
do i = 1 to n;
t = catx('/',strip(t),dequote(scan(p,i,"~","Q")));
end;
t = "/" !! strip(t) !! "/";
put "expected: /Medical Insurance/Left Atrial Appendage (LAA)/";
put "produced: " t;
run;
a) count number of "words" in string
b) scan it one-by-one in loop
c) delete quotes using proper function i.e. DEQUOTE()
d) concat it together using CATX() function
e) add leading and trailing "/"
d) enjoy
Bart
Add the STRIP() function:
target = catx("~",target,quote(strip(compress(word,'0D0A'x))));
@Kurt_Bremser thank you as it resolved the issue. However I'm getting the other issue in next step. Here the idea I want to unquote the values.
Code:
data _null_; test =cats( '/', catx('/',%unquote(¶meter_2)) , '/'); put test=; run;
Log:
44 data _null_; 45 /*test = '/'||¶meter_2||'/'; */ 46 test =cats( '/', catx('/',%unquote(¶meter_2)) , '/'); SYMBOLGEN: Macro variable PARAMETER_2 resolves to "Medical Insurance"~"Left Atrial Appendage(LAA)" NOTE: Line generated by the macro function "UNQUOTE". 46 "Medical Insurance"~"Left Atrial Appendage(LAA) ----------------- 22 76 ERROR 22-322: Syntax error, expecting one of the following: <, <=, =, >, >=, EQ, GE, GT, LE, LT, NE, NG, NL, ^=, ~=. ERROR 76-322: Syntax error, statement will be ignored.
Excepted Results:
/Medical Insurance/Left Atrial Appendage(LAA)/
Don't add the quotes in the first place, when you later need to remove them.
The macro function %UNQUOTE has a completely different function than removing quotes, it is used to unmask macro elements if those have been masked by one of the macro quoting functions.
To remove quotes from a string in a data step, use COMPRESS.
@Kurt_Bremser I want to add quotes in the previous step. Any help to tweak the below program to generate the result with quote but with slash (/).
data _null_;
/*test = '/'||¶meter_2||'/'; */
test =cats( '/', catx('/',%unquote(¶meter_2)) , '/');
put test=;
run;
Desired results:
/"Medical Insurance"/"Left Atrial Appendage (LAA)"/
This is going nowhere. I already told you and pointed you to the documentation, SO WHY ARE YOU STILL USING THE MACRO FUNCTION???
In the beginning, you start with a comma-separated text in a macro variable. With what do you want to end up, and for which purpose(s)?
@Kurt_Bremser This is the second question and connected with the original post. I did removed the macro function and used compress but still ended up with this error.
You can ignore previous question as it led to confusion.
data _null_; /*test = '/'||¶meter_2||'/'; */ test =cats( '/', catx('/',compress(¶meter_2,'kas')) , '/'); put test=; run;
Value of Parameter_2 is "Medical Insurance"~"Left Atrial Appendage (LAA)"
Log:
81 data _null_; 82 /*test = '/'||¶meter_2||'/'; */ 83 test =cats( '/', catx('/',compress(¶meter_2,'kas')) , '/'); NOTE: Line generated by the macro variable "PARAMETER_2". 83 "Medical Insurance"~"Left Atrial Appendage(LAA)" -------------------------------------- 22 76 ERROR 22-322: Syntax error, expecting one of the following: <, <=, =, >, >=, EQ, GE, GT, LE, LT, NE, NG, NL, ^=, ~=. ERROR 76-322: Syntax error, statement will be ignored.
Excepted result:
/Medical Insurance/Left Atrial Appendage (LAA)/
Quote from myself:
In the beginning, you start with a comma-separated text in a macro variable. With what do you want to end up, and for which purpose(s)?
I will not respond any further until you have answered this question.
@Kurt_Bremser In real life value for the macro variable parameter_2 comes from webpage and we are adding quotes and separator for SAS to process the list of values. After processing, I was asked to get the value of macro variable in other new macro variable (test in my case) separated by slash '/'.
Because original macro variable parameter_2 will go through multiple processing after the steps I shown in the original post. So this new macro variable 'test' will tell us the values for which the job is being processed.
@Babloo wrote:
@Kurt_Bremser In real life value for the macro variable parameter_2 comes from webpage and we are adding quotes and separator for SAS to process the list of values. After processing, I was asked to get the value of macro variable in other new macro variable (test in my case) separated by slash '/'.
Because original macro variable parameter_2 will go through multiple processing after the steps I shown in the original post. So this new macro variable 'test' will tell us the values for which the job is being processed.
I'm afraid this makes no sense to me.
You don't need quotes in a macro variable to perform any particular step. And so we have had at least two earlier threads from you, which were rather long, about how to put quotes around, and now you want to find out how to remove the quotes at the end. As Kurt said, don't put quotes in macro variables. Sometimes, you cause your own problems.
Keep the original, simply comma-separated value as is, and create special forms in new macro variables wherever needed. Don't go through the trouble of transforming and de-transforming the original variable with every sub-task.
1) First and foremost!
If you have a "user input" in a macrovariable NEVER(!) call it by ¯ovariable.
Always user SYMGET() function!
What if macrovariable value is: "; run; x 'format C:\';;
?
The symget() will push the value directly into a text variable without any risk and the & will "blow up" the system...
2) Do it like this:
/* input: */
%let Parameter_2 = "Medical Insurance"~"Left Atrial Appendage (LAA)";
/* process: */
data _null_;
length p $ 32767;
p=symget('Parameter_2');
t=p; /* to get P's length */
n=countw(t,"~","Q");
t='';
do i = 1 to n;
t = catx('/',strip(t),dequote(scan(p,i,"~","Q")));
end;
t = "/" !! strip(t) !! "/";
put "expected: /Medical Insurance/Left Atrial Appendage (LAA)/";
put "produced: " t;
run;
a) count number of "words" in string
b) scan it one-by-one in loop
c) delete quotes using proper function i.e. DEQUOTE()
d) concat it together using CATX() function
e) add leading and trailing "/"
d) enjoy
Bart
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.