BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
Babloo
Rhodochrosite | Level 12

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 = "&parameter_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: &parameter_2.;

 

Log:

 

94   %put ####parameter_2 is: &parameter_2.;
####parameter_2 is: "Medical Insurance                                     "~"Left Atrial Appendage  (LAA)                  
"

Desired Result:

 

####parameter_2 is: "Medical Insurance"~"Left Atrial Appendage Closure (LAA)"
1 ACCEPTED SOLUTION

Accepted Solutions
yabwon
Onyx | Level 15

1) First and foremost!

If you have a "user input" in a macrovariable NEVER(!) call it by &macrovariable.

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

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



View solution in original post

11 REPLIES 11
Babloo
Rhodochrosite | Level 12

@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(&parameter_2)) , '/');
put test=;
run;

Log:

 

44   data _null_;
45   /*test = '/'||&parameter_2||'/'; */
46   test =cats( '/', catx('/',%unquote(&parameter_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)/
Kurt_Bremser
Super User

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.

Babloo
Rhodochrosite | Level 12

@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 = '/'||&parameter_2||'/'; */
test =cats( '/', catx('/',%unquote(&parameter_2)) , '/');
put test=;
run;

Desired results:

 

/"Medical Insurance"/"Left Atrial Appendage (LAA)"/
Kurt_Bremser
Super User

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)?

Babloo
Rhodochrosite | Level 12

@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 = '/'||&parameter_2||'/'; */
test =cats( '/', catx('/',compress(&parameter_2,'kas')) , '/');
put test=;
run;

 

Value of Parameter_2 is "Medical Insurance"~"Left Atrial Appendage (LAA)"

 

Log:

81   data _null_;
82   /*test = '/'||&parameter_2||'/'; */
83   test =cats( '/', catx('/',compress(&parameter_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)/
Kurt_Bremser
Super User

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.

Babloo
Rhodochrosite | Level 12

@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. 

PaigeMiller
Diamond | Level 26

@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.

--
Paige Miller
Kurt_Bremser
Super User

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.

yabwon
Onyx | Level 15

1) First and foremost!

If you have a "user input" in a macrovariable NEVER(!) call it by &macrovariable.

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

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
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
  • 11 replies
  • 1636 views
  • 8 likes
  • 4 in conversation