前两天问了个问题:
https://bbs.pinggu.org/thread-2221015-1-1.html
%let a=you are how;
怎么生成宏变量b变成 how are you
求助...........
一个很简单的问题,各位朋友给出了很多不同的做法,我认真地学习了一下,也借此给各位分享一下
/*方案1:很简单*/
%macro inverse(a=);
%let i=1;
%let var=1;
%let b=;
%do %while(&var^=);
%let var=%scan(&a,&i);
%let b=&var &b;
%let i=%eval(&i+1);
%end;
%put &b;
%mend;
%inverse(a=sir you are how )
/*方案2:scan函数从后面截取*/
%macro inverse2(a=);
%let i=-1;
%let var=1;
%let b=;
%do %while(&var^=);
%let var=%scan(&a,&i);
%let b=&b &var;
%let i=%eval(&i-1);
%end;
%put &b;
%mend;
%inverse2(a=sir you are how)
/*方案3:利用data步,从最后一位依次读入,然后再生成宏变量*/
data a;
%let a=sir you are how;
i=-1;
var="whatever";
do until(var="");
var=scan("&a",i);
output;
i+(-1);
end;
run;
proc sql noprint;
select var into:b separated by " " from a;
quit;
%put &b;
/*方案4:先对整个宏变量倒置,再对倒置后宏变量内的每个单词倒置 playmore贡献*/
options symbolgen=no;
%macro ReverseString(a=);
%let a_temp=%SYSFUNC(REVERSE(&a));
%let b=;
%do i=1 %to %EVAL(%SYSFUNC(COUNT(&a,%STR( )))+1); /*第一次知道,数空格个数可以这样数%str(),看了bobguy的代码,发现这里有缺陷,count寻找substring,如果原变量不同单词以多个空格隔开,就会出现计数错误,用%cmpres可以将多个空格变成一个,并删除头尾空格*/
%let b=&b %SYSFUNC(REVERSE(%SCAN(&a_Temp,&i)));
%end;
%put &b;
%mend;
%ReverseString(a=sir you are how);
/*方案5:还是利用data步,countw可以直接计算有多少单词,Bridgenc贡献*/
data b;
%let a=sir you are how;
format d $100.;
k=countw("&a");
do i=1 to k;
c=scan("&a",-i," ");
d=catx(" ",d,c);
end;
call symput ("b",d);
run;
%put &b;
/*方案6: %cmpres Compress multiple blanks and remove leading and trailing blanks。 bobguy贡献*/
%macro inverse(varlist=);
%let n= %eval(%sysfunc(countc(%cmpres(&varlist),%str( )))+ (%length(&varlist) gt 0) );
%let name1=;
%do i=&n %to 1 %by -1;
%let name1=&name1 %scan(&varlist,&i) ;
%end;
%put &name1;
%mend;
%inverse(varlist=you are how)
/*总结一下:做循环,很多时候计算循环次数,就要看有多少单词,其中countw最直接最好用,countc,count如果有多个分隔符要小心。用do while, do until 不需要知道循环的次数,是一个简单的方法。*/
/*scan函数可以从右边读取单词,把i 设置成负数就可以了。*/
/*%sysfunc*/
/*reverse*/
/*%cmpres*/
/*%str( );*/