DATA Step, Macro, Functions and more

tranwrd special characters

Accepted Solution Solved
Reply
Frequent Contributor
Posts: 124
Accepted Solution

tranwrd special characters

Hello

I would like to obtain &vars2, &vars3 and &vars4 automatically from &vars1

%let vars1 = Id Germ Gender PostCode DateOfDiagnosis DateOfBirth;

%let vars2 = 'Id','Germ','Gender','PostCode','DateOfDiagnosis','DateOfBirth';

%let vars3 = '_Id','_Germ','_Gender','_PostCode','_DateOfDiagnosis','_DateOfBirth';

%let vars4 = Id=_Id Germ=_Germ Gender=_Gender PostCode=_PostCode DateOfDiagnosis=_DateOfDiagnosis DateOfBirth=_DateOfBirth;

I'm able to obtain _Id_Germ_Gender_PostCode_DateOfDiagnosis_DateOfBirth_

with this :

%put %sysfunc(cat(_,%sysfunc(tranwrd(&vars1,%str( ),%str(_))),_));

So I think this should be working for &vars2 but it is not :

%put %sysfunc(cat(%str('),%sysfunc(tranwrd(&vars1,%str( ),%str(','))),%str(')));

Does anyone knows how to handle special characters like ' and , ?

Thanks


Accepted Solutions
Solution
‎05-30-2012 07:09 AM
Respected Advisor
Posts: 3,777

Re: tranwrd special characters

Using macro language and tranwrd is going to be too fiddley.  Using this technique will allow you much more flexibility.

data test;

   stop;

   length Id $8 Germ $3 Gender $1 PostCode $6 DateOfDiagnosis DateOfBirth 8;

   format date: date9.;

   call missing(of _all_);

   run;

%let vars1 = ID G: post: date:;

proc transpose data=test(obs=0) out=vars;

   var &vars1;

   run;

proc sql noprint;

   select _name_,

         quote(strip(_name_)),

         quote(cats('_',_name_)),

         catx('=_',_name_,_name_)

   into :vars1 separated by ' ',

        :vars2 separated by ',',

        :vars3 separated by ',',

        :vars4 separated by ' '

   from vars;

   quit;

   run;

%put NOTE: VARS1=%superQ(vars1);

%put NOTE: VARS2=%superQ(vars2);

%put NOTE: VARS3=%superQ(vars3);

%put NOTE: VARS4=%superQ(vars4);

View solution in original post


All Replies
Solution
‎05-30-2012 07:09 AM
Respected Advisor
Posts: 3,777

Re: tranwrd special characters

Using macro language and tranwrd is going to be too fiddley.  Using this technique will allow you much more flexibility.

data test;

   stop;

   length Id $8 Germ $3 Gender $1 PostCode $6 DateOfDiagnosis DateOfBirth 8;

   format date: date9.;

   call missing(of _all_);

   run;

%let vars1 = ID G: post: date:;

proc transpose data=test(obs=0) out=vars;

   var &vars1;

   run;

proc sql noprint;

   select _name_,

         quote(strip(_name_)),

         quote(cats('_',_name_)),

         catx('=_',_name_,_name_)

   into :vars1 separated by ' ',

        :vars2 separated by ',',

        :vars3 separated by ',',

        :vars4 separated by ' '

   from vars;

   quit;

   run;

%put NOTE: VARS1=%superQ(vars1);

%put NOTE: VARS2=%superQ(vars2);

%put NOTE: VARS3=%superQ(vars3);

%put NOTE: VARS4=%superQ(vars4);

Frequent Contributor
Posts: 124

Re: tranwrd special characters

Thanks very much !

I simplified it a bit to meet my needs :

%let vars1 = Id Germ Gender PostCode DateOfDiagnosis DateOfBirth;

data test;

  stop;

  length &vars1 $3;

  run;

proc transpose data=test(obs=0) out=vars;

   var _all_;

   run;

proc sql noprint;

  select

  quote(strip(_name_)),

  quote(cats('_',_name_)),

  catx('=_',_name_,_name_)

  into

  :vars2 separated by ',',

  :vars3 separated by ',',

  :vars4 separated by ' '

  from vars;

  quit;

  run;

%_eg_conditional_dropds(test, vars);

%put &vars1;

%put &vars2;

%put &vars3;

%put &vars4;

Respected Advisor
Posts: 3,777

Re: tranwrd special characters

%let vars1 = Id Germ Gender PostCode DateOfDiagnosis DateOfBirth;

data test;

  stop;

  length &vars1 $3;

  run;

This is the part that I assumed you already have "a SAS data set".

Regular Contributor
Posts: 241

Re: tranwrd special characters

there seem to be bugs to be ironed out in handling macro quoted arguments in the functions called through %sysfunc(). there seem to be ways to around them, though. here is one. admittedly, var4 is stretching macro a bit. :-)

  %*-- note: macro args whose name starts with an underscore character are for calling-by-name --*;
 
  %*-- returns 1 if &&&_arg is blank, 0 otherwise --*;
  %macro isBlank(_arg);
    %sysevalf(%superq(&_arg) = ,boolean)
  %mend isBlank;
 
  %*-- returns &&&_str single or double quoted or as-is. macro quoted --*;
  %macro qquote(_str, quote=s);
    %local str sq;
 
    %let str = %superq(&_str);
    %let quote = %upcase(&quote);
 
    %if %isBlank(quote) %then %do;
      %*;&str
    %end; %else %if &quote = S %then %do;
      %let sq = %str(%');
      %*;&sq.%qsysfunc(transtrn(&str,&sq,&sq.&sq))&sq
    %end; %else %do;
      %*;%qsysfunc(quote(&str)) 
    %end;
  %mend qquote;
 
  %*-- returns &str prefixed --*;
  %macro prefix(str, prefix=);
    %*;%unquote(&prefix)&str
  %mend  prefix;
 
  %*-- main. returns prefixed, delimited, and quoted list --*;
   %macro qcsv(_list, indlm=%str( ), dlm=%str(, ), quote=s, prefix=);
    %local word i;
    %let i = 1;
    %let word = %qscan(%superq(&_list), &i, &indlm);
    %do %while (not %isBlank(word));
      %let word = %prefix(&word, prefix=&prefix);
      %*;%qquote(word, quote=&quote)
      %let i = %eval(&i + 1);
      %let word = %qscan(%superq(&_list), &i, &indlm);
      %if not %isBlank(word) %then %*;&dlm.;
    %end;
  %mend;
 
  %*-- usage example --*;
  %let vars1 = Id Germ Gender PostCode;
  %put var2=%qcsv(vars1);
  %put var3=%qcsv(vars1, prefix=_);
  %put var4=%qcsv(vars1, quote=, prefix=%nrstr(&str=_));
  %*-- on log
  var2='Id', 'Germ', 'Gender', 'PostCode'
  var3='_Id', '_Germ', '_Gender', '_PostCode'
  var4=Id=_Id, Germ=_Germ, Gender=_Gender, PostCode=_PostCode
  --*;

☑ This topic is SOLVED.

Need further help from the community? Please ask a new question.

Discussion stats
  • 4 replies
  • 832 views
  • 1 like
  • 3 in conversation