|
Chang,
very good idea, but I think that the solution should be able to work
with just about any macro variable names (preferably all but SYSPBUFF,
which is always local). My suggestion is to make a macro call qDoOver,
which does the same thing as your %DoOver, except that the output is
quoted:
%macro qDoOver(list, phrase=?, between=%str( ));
%local i item;
%let i = 1;
%let item = %scan(&list, &i);
%do %while (&item^=);
%do;%qsysfunc(tranwrd(&phrase, ?, &item))%end;
%let i = %eval(&i + 1);
%let item = %scan(&list, &i);
%if (&item^=) %then %do;&between%end;
%end;
%mend qDoOver;
I took the liberty of replacing your ingenious, but hard to fathom, use
of "%*;" to remove spurious blanks in the macro output, and instead
imbedded the macro output in "%do;....%end;", otherwise the only
change from your %DoOver is the use of %qsysfunc rather than %sysfunc.
%qDoOver is used thus in the %MACUP macro:
%macro macup / parmbuff;
%unquote(%qDoOver(%scan(&syspbuff,1,()),
phrase=%nrstr(%let ?=%upcase(&?);),
between=))
%mend;
I did not make a special macro to avoid error messages when trying to
upcase non-existing variables - I think such error messages can save
quite a lot of debugging time.
Submitting
%let item=test;
%let phrase=test2;
%let i=hoopla;
%macup(item phrase i);
%put &item &phrase &i;
writes "TEST TEST2 HOOPLA" in the log, in other words the global,
rather than the local, variables got upcased, just as I wanted.
I really like this approach, I also think it is much better than my
own original suggestion.
Regards,
Søren
On Mon, 1 Nov 2010 14:38:25 -0400, Chang Chung <chang_y_chung@HOTMAIL.COM>
wrote:
>On Fri, 29 Oct 2010 20:34:49 -0400, Tyler Lonczak <lonczakt@GMAIL.COM>
>wrote:
>...
>>I recently wrote a macro to UPCASE multiple macro vars at the same
>>time. The code is below. I would appreciate any feedback on it.
>>
>>%MACRO MacUp(Vars);
>> %LOCAL I J;
>> %DO I = 1 %TO %SYSFUNC(COUNTC(&vars,' '))+1;
>> %LET J = &%SCAN(&vars,&I);
>> %LET %SCAN(&vars,&I) = %UPCASE(&J);
>> %END;
>>%MEND;
>>
>>%LET Admin = 1;
>>%LET State = ME;
>>%LET Replevel = Dis;
>>
>>%PUT &admin &state &replevel;
>>%MACUP(admin state replevel);
>>%PUT &admin &state &replevel;
>>
>Hi, Tyler,
>
>Welcome to the wonderful world of sas macros!
>
>An interesting possibility to improve upon your macro is to separate the
>looping (over a blank delimited list of words) part out into its own macro,
>so that you don't have to code that part again. For another example, see
>http://tinyurl.com/bk843m or
>http://www.listserv.uga.edu/cgi-bin/wa?A2=ind0806D&L=sas-l&P=R21977&D=1&O=D
>Hope this helps a bit.
>Cheers,
>Chang
>
>%macro doOver(list, phrase=?, between=%str( ));
> %local i item;
> %let i = 1;
> %let item = %scan(&list, &i);
> %do %while (&item^=);
> %*;%sysfunc(tranwrd(&phrase, ?, &item))
> %let i = %eval(&i + 1);
> %let item = %scan(&list, &i);
> %if (&item^=) %then %*;≬
> %end;
>%mend doOver;
>
>%*-- given a name of a macro var, upcase the content --*;
>%macro myUpcase(_mvar);
> %if not %symexist(&_mvar) %then %return;
> %let &_mvar = %upcase(&&&_mvar);
>%mend myUpcase;
>
>%*-- check --*;
>%let admin = 1;
>%let state = me;
>%let replevel = Dis;
>
>%*-- upcase the values of the macro vars. --*;
>%doOver(admin state replevel, phrase=%nrstr(
> %myUpcase(?)
>))
>
>%put &admin &state &level;
>%*-- on log
>1 ME DIS
>--*;
|