how is it possible to get from this list:
%let types =
'TYPE 1'
'TYPE 2';
to this list, programmatically:
%let new =
AT_TYPE_1
AT_TYPE_2;
My unsuccessful attempt:
%let new= %sysfunc(translate(&types, '_',' '));
For your specific example you could possible get away with something like this that just changes the 'TYPE ' to 'AT_TYPE_' and then removes the qutoes.
%let new=%sysfunc(compress(%sysfunc(tranwrd(&types,%str(TYPE ),AT_TYPE_)),%str(%')));
But if this is just an example of a larger problem of converting a space delimited list of quoted values into a space delimited unquoted values with any embedded spaces converted to underscores then you will need a loop. Probably easier to do in a data step than in macro.
data _null_;
length types new $32767 ;
types = symget('types');
do i=1 to countw(types,' ','q');
new = catx(' ',new,translate(catx(' ','AT',dequote(scan(types,i,' ','q'))),'_',' '));
end;
call symputx('new',new);
stop;
run;
If you did need to do total in macro code then perhaps you could use a function style macro.
%macro labels_to_names(labels,prefix=);
%local i;
%do i=1 %to %sysfunc(countw(&labels,%str( ),q));
%sysfunc(translate(&prefix %sysfunc(dequote(%scan(&labels,&i,%str( ),q))),_,%str( )))
%end;
%mend labels_to_names;
%let new=%labels_to_names(&types,prefix=AT);
How is the first variable determined? Is there a way to go back and fix at source?
I need to use both versions...
Maybe you can work something out from the following snippet
%let types =
'TYPE 1'
'TYPE 2';
data _null_;
call symputx("new",prxchange("s/'(\D+)\s+(\d+)'/AT_\1_\2/i",-1,"&types"));
run;
%put &new;
You can achieve that via data step or macro . I suggest including them all into a macro.
%macro change(t=);
%let n=%sysfunc(countw(&t ,%str(%') ));
%do i=1 %to &n ;
%let temp=%scan(&t, &i ,%str(%'));
%if %length(&temp) ne 0 %then %do;
AT_%sysfunc(translate(&temp,_,%str( )))
%end;
%end;
%mend;
%let types =
'TYPE 1'
'TYPE 2';
%let want=%change(t=&types) ;
%put NOTE: &want ;
Do you have to create the let-statement or do you just need new to be set properly?
If you are interested in the value, try:
%let new = %sysfunc(tranwrd(%sysfunc(compress(&types, %str(%'))), %str(TYPE ), %str(AT_TYPE_)));
For your specific example you could possible get away with something like this that just changes the 'TYPE ' to 'AT_TYPE_' and then removes the qutoes.
%let new=%sysfunc(compress(%sysfunc(tranwrd(&types,%str(TYPE ),AT_TYPE_)),%str(%')));
But if this is just an example of a larger problem of converting a space delimited list of quoted values into a space delimited unquoted values with any embedded spaces converted to underscores then you will need a loop. Probably easier to do in a data step than in macro.
data _null_;
length types new $32767 ;
types = symget('types');
do i=1 to countw(types,' ','q');
new = catx(' ',new,translate(catx(' ','AT',dequote(scan(types,i,' ','q'))),'_',' '));
end;
call symputx('new',new);
stop;
run;
If you did need to do total in macro code then perhaps you could use a function style macro.
%macro labels_to_names(labels,prefix=);
%local i;
%do i=1 %to %sysfunc(countw(&labels,%str( ),q));
%sysfunc(translate(&prefix %sysfunc(dequote(%scan(&labels,&i,%str( ),q))),_,%str( )))
%end;
%mend labels_to_names;
%let new=%labels_to_names(&types,prefix=AT);
Thanks - I used the data step method as I found it adapted very easily to the true original list of items, which weren't actually TYPE 1, TYPE 2 etc.
The easiest way is to use Base SAS - which is designed to process and manipulate data, rather than Macro language which is designed to generate text, here are some verbose examples of generating macro variables from code, or using a dataset in programming rather than macro variables:
data myparameters; param="SEX"; val="M"; output; val="F"; output; run; /* Create some macro variables from my parameters */ data _null_; set myparameters; by param; length string1-string3 $200; retain string1 string2 string3; string1=catx(" ",string1,val); string2=catx(",",string2,val); string3=cat(strip(string3),",'",strip(val),"'"); if last.param then do; call symput('string1',string1); call symput('string2',string2); call symput('string3',string3); end; run; %put &string1.; %put &string2.; %put &string3.; /* Or we could just use that parameter dataset in code and not need macro at all */ proc sql; create table WANT as select * from SASHELP.CLASS where SEX in (select VAL from MYPARAMETERS where PARAM="SEX"); quit;
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.