BookmarkSubscribeRSS Feed
ankitk321
Fluorite | Level 6

After removing the %str from the below code it will not work and my values is coming from a call symput macro variable.Kindly help me how to resolve the same. I want to use it as ----> %let string=a,123;b,321;c,456;d,789;e,888;

 

 

%global string;

%let string=%str(a,123;b,321;c,456;d,789;e,888);

%put "&string.";

options mprint mlogic symbolgen;

%macro test;

%let word_cnt = %eval(%sysfunc(countc("&string.",';'))+1);/* Problem in this line */

%let count= &word_cnt;

%put &word_cnt.;                                                                                  */

%do i = 1 %to &word_cnt.;

 

%let var&i=%sysfunc(trim(%qscan(&string.,&i,%str(';')))); /* Problem in this line...rest every thing is fine */                                                              

%put &&var&i;                                                                                                          

%end; 

%do j=1 %to 5;

%let dataset_key&j= %scan(%quote(&&var&j),1,%str(","));

%let dataset_Name&j= %scan(%quote(&&var&j),2,%str(","));

%put &&dataset_key&j;

%put &&dataset_Name&j;

%end;

% put &string;

%mend test;  

                  

%test;

 

6 REPLIES 6
PaigeMiller
Diamond | Level 26

Don't make us do work you have already done. SHOW US THE SASLOG (and put the options mprint mlogic symbolgen; statement at the top of your code)

--
Paige Miller
novinosrin
Tourmaline | Level 20
%macro test;

%let word_cnt = %eval(%sysfunc(countw(&string,%str(;)))+1);/* Problem in this line */

%let count= &word_cnt;

%put &word_cnt.;                                                                                

%do i = 1 %to &word_cnt.;

 

%let var&i=%sysfunc(trim(%qscan(&string,&i,%str(;)))); /* Problem in this line...rest every thing is fine */                                                              

%put &&var&i;                                                                                                          

%end; 

%do j=1 %to 5;

%let dataset_key&j= %scan(%quote(&&var&j),1,%str(,));

%let dataset_Name&j= %scan(%quote(&&var&j),2,%str(,));

%put &&dataset_key&j;

%put &&dataset_Name&j;

%end;

%put &string;

%mend test;  
%test
ballardw
Super User

And just what is the problem?

For one thing

%let string=a,123;b,321;c,456;d,789;e,888;

The definition of string ends at the first semicolon as the end of the %let statement. Almost any time the delimiters , or ; are used you are causing your one problems. So why do you have them? I do not see any use for of &string that requires the delimiters.

If you have paired values it might be better to have two space delimited lists instead of a complex

 

%macro dummy;
%let vstring=a  b  c  d  e ;
%let nstring= 123  321  456  789  888;
%let word_cnt = %sysfunc(countw(&vstring));
%put word_cnt= &word_cnt;
%do i=1 %to &word_cnt;
   %let var&i = %scan(&vstring,&i);
   %let num&i = %scan(&nstring,&i);

   %put var&i= &&var&i;
   %put num&i= &&num&i;

%end;
%mend;
%dummy;
Tom
Super User Tom
Super User

There is some strange interaction between using %SYSFUNC() in a complex statement inside of a macro and your delimiters.

For example this code works fine outside of a macro.

data _null_;
  call symputx('string','a,123;b,321;c,456;d,789;e,888');
run;
%let string=%superq(string);

%put &=string;
%put Nwords = %sysfunc(countw(&string,%str(;)));

Or even inside a macro:

data _null_;
  call symputx('string','a,123;b,321;c,456;d,789;e,888');
run;

%macro test;
%let string=%superq(string);

%put &=string;
%put Nwords = %sysfunc(countw(&string,%str(;)));
%mend test;
%test;

But try to use that SYSFUNC() call in a %DO statement and it bombs.

%macro test;
%local i;
%let string=%superq(string);
%do i=1 %to %sysfunc(countw(&string,%str(;)));
  %put &=i ;
%end;
%mend test;
%test;
1655  %test;
ERROR: Expected close parenthesis after macro function invocation not found.
NOTE: One or more missing close parentheses have been supplied for the %COUNTW function.
ERROR: Expected close parenthesis after macro function invocation not found.
ERROR: %EVAL function has no expression to evaluate, or %IF statement has no condition.
ERROR: The %TO value of the %DO I loop is invalid.
ERROR: The macro TEST will stop executing.

But if you just assign the count to a macro variable all is well again.

%macro test;
%local i n;
%let string=%superq(string);
%let n= %sysfunc(countw(&string,%str(;)));
%do i=1 %to &n;
  %put &=i ;
%end;
%mend test;
%test;

And it works fine

1664  %test;
I=1
I=2
I=3
I=4
I=5

You have other problems with your macro. 

You are including quotes in the arguments to the %SCAN() function which is going to cause issues. the %SCAN() function treats all of the characters you give it as delimiters.  So if your string includes quotes and you tell %scan() that the delimiters are quote, semi-colon (and redundantly quote again) then you might not parse the string properly.

 

The logic of it seems strange. Why are you making a series of macro variables? Why not just use the value as you derive it?

%macro test;
  %local i n word dataset_key dataset_name ;
  %let string=%superq(string);
  %let n= %sysfunc(countw(&string,%str(;)));
  %do i = 1 %to &n;
    %let word=%qscan(&string,&i,%str(;));
    %let dataset_key = %scan(&word,1,%str(,));
    %let dataset_name = %scan(&word,2,%str(,));
    %put &=i &=word &=dataset_key &=dataset_name ;
  %end;
%mend ;
1731  data _null_;
1732    call symputx('string','a,123;b,321;c,456;d,789;e,888');
1733  run;

1734  %test;
I=1 WORD=a,123 DATASET_KEY=a DATASET_NAME=123
I=2 WORD=b,321 DATASET_KEY=b DATASET_NAME=321
I=3 WORD=c,456 DATASET_KEY=c DATASET_NAME=456
I=4 WORD=d,789 DATASET_KEY=d DATASET_NAME=789
I=5 WORD=e,888 DATASET_KEY=e DATASET_NAME=888
ankitk321
Fluorite | Level 6

Thanks a ton it works for me.

mkeintz
PROC Star

I like @Tom's solution to the problem as you presented it.  His response is a nice demonstration of the usefulness of the SUPERQ macro function.

 

But why use a semi-colon as a group delimiter in the first place?  Yes, you can make two lists as @ballardw suggested, but you could also chose a delimiter like !, as in

   %let string = a,123!b,321!c,456!d,789!e,888;

 

This would allow you to drop the %STR usage, and the rest of your code logic would need no changes except for specifying ! as the group delimiter.  Just choose a delimiter that you know will not be part of the string value, and does not need masking by %STR.

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

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
  • 6 replies
  • 931 views
  • 3 likes
  • 6 in conversation