Reputation: 113
I want to replace space between variables passed in a macro variable with double quotes with space, i.e. " ". Please find below the code I am using for the same and the result I am getting.
%let str7=ABC DEF UVW XYZ;
%let str8 = %qsysfunc(quote(%qsysfunc(tranwrd(%qsysfunc(compbl(%qsysfunc(strip(%upcase(&str7.))))),%str( ),%nrstr(%")))));
%put ^^^^&str8;
The Log Displays:
18 %put ^^^^&str8;
^^^^"ABC""DEF""UVW""XYZ"
I need this to be "ABC" "DEF" "UVW" "XYZ".
I have also tried the following...
proc fcmp outlib=work.funcs.funcs;
function delimit_words(iString $) $;
result = '"' || tranwrd(cats(compbl(iString))," ", '" ,"') || '"';
return (result );
endsub;
run;
%let x = A B C ;
%let y = %sysfunc(delimit_words(&x));
%put &y;
but it gives me following error...
ERROR: The DELIMIT_WORDS function referenced in the %SYSFUNC or %QSYSFUNC macro function is not found.
I have used the following approach given by Jeff.
data test;
id =1; _var="ABC"; output;
id =1; _var="DEF"; output;
id =1; _var="UVW"; output;
id =2; _var="UVW"; output;
id =3; _var="ABC"; output;
id =3; _var="UVW"; output;
id =3; _var="XYZ"; output;
id =4; _var="ABC"; output;
id =4; _var="XYZ"; output;
run;
%macro __test1(_byvar=, _qnam=, _id=);
proc sort data= test out=_test;
by &_byvar.;
%if %superq(_qnam) ne %then
%do;
%let __tmpmv_qnam = %qsysfunc(prxchange(%bquote(s/\b/"/),-1,%bquote(&_qnam)));
*";
%put ^^^^^&__tmpmv_qnam.;
where upcase(&_id) in (&__tmpmv_qnam);
%end;
run;
%mend;
%__test1 (_byvar=id ,_qnam = ABC UVW, _id=_var);
The log diaplayed following error:
SYMBOLGEN: Macro variable _QNAM resolves to ABC UVW
ERROR: Literal contains unmatched quote.
Please help on this one.
Upvotes: 1
Views: 2138
Reputation: 51621
As long as you want to use double quotes then I think you are working way too hard.
%let str7=ABC DEF UVW XYZ;
%let str8="%sysfunc(tranwrd(&str7,%str( )," "))";
Now if your original string is not well formed and might contain multple spaces between words then you will first need to use %COMPBL()
to clean it up.
%let str8=%sysfunc(compbl(&str7));
%let str8="%sysfunc(tranwrd(&str8,%str( )," "))";
Upvotes: 1
Reputation: 1
Try this:
%let str7=ABC DEF UVW XYZ;
%let str8 ="%bquote(%sysfunc(tranwrd(%sysfunc(strip(&str7.)),%str( ),%nrstr(%",%"))))";
%put ^^^^&str8;
Upvotes: 0
Reputation: 63434
Your FCMP
works fine if you add the line
options cmplib=work.funcs;
to your code, if you're running in SAS 9.3 or later.
In general, the best approach is not to do this: instead create the macro variable with quotes in the first place. How did you create this? If you created it from a dataset, for example, you could have done:
proc sql;
select quote(strip(name)) into :varlist separated by ','
from sashelp.class;
quit;
which returns
"Alfred","Alice","Barbara","Carol","Henry","James","Jane","Janet","Jeffrey","John","Joyce","Judy" ,"Louise","Mary","Philip","Robert","Ronald","Thomas","William"
Upvotes: 1
Reputation: 1807
Without debugging either of your approaches above, I can offer a third:
%let str8 = %sysfunc(prxchange(%bquote(s/\b/"/),-1,%quote(&str7.)));
*";
The prxchange()
function tells SAS to replace every word boundary (\b
) with a "
. As far as when to use bquote()
, vs quote()
, it's all documented online, but honestly I usually resort to trial and error.
The *";
does nothing, but it makes things look nicer if your editor's syntax highlighting gets confused by the single quote (like mine does).
Upvotes: 0