我想在%let调用中使用宏,下面是宏代码以及我想如何调用它。请帮助我实现它。
%macro xscan(string, delimiter, word_number);
%let len1=%length(&string); /*Computing the length of the string*/
%let len=%eval(&len1+1);
%let sub=%scan(&string,&word_number,"&delimiter"); /*Fetch the string specified by word_number*/
%if &word_number ge 0 %then %do;
%let pos=%index(&string,&sub); /* Locate the position while reading left to right*/
%end;
%if &word_number lt 0 %then %do;
data _null_;
pos=find("&string","&sub",-&len); /* Locate the position while reading from right to left*/
call symput("pos",pos);
run;
%end;
%let strg=%substr(&string,&pos); /* Extract the substring*/
%put the string is &strg;
%mend;
%let sub_str = %xscan(a bb ccc dddd bb eeeee, %str( ), -2);
%put The value of sub_str = &sub_str;
期望的实施:
data work.in_data;
length in_string $50;
in_string = “a bb ccc dddd bb eeeee”;
output;
in_string = “aa b cc aa dee”;
output;
run;
data work.out_data;
set work.in_data;
length sub_str $50;
start_word_num = -(_n_ +1);
sub_str = %xscan(in_string,’ ‘, start_word_num);
run;
proc print; run;
答案 0 :(得分:1)
你有两个问题。首先,函数式宏不得包含任何数据步骤(或procs或其他任何内容)。如果确实需要执行数据步骤,则必须将FCMP与run_macro配合使用。但是,您可以使用%SYSFUNC
来完成数据步骤中的操作。
其次,您需要实际返回该值。最终宏会解析为文本,因此您需要解析
%let x = %xscan(...);
到
%let x = bb eeeee;
所以你需要在你的宏中将bb eeeee作为开放文本。
这应该完成两件事:
options mprint symbolgen;
%macro xscan(string, delimiter, word_number);
%local len1 len sub pos;
%let len1=%length(&string); /*Computing the length of the string*/
%let len=%eval(&len1+1);
%let sub=%scan(&string,&word_number,"&delimiter"); /*Fetch the string specified by word_number*/
%if &word_number ge 0 %then %do;
%let pos=%index(&string,&sub); /* Locate the position while reading left to right*/
%end;
%else %if &word_number lt 0 %then %do;
%let pos=%sysfunc(find(&string,&sub,-&len)); /* Locate the position while reading from right to left*/
%end;
%substr(&string,&pos) /* Extract the substring*/
%mend;
%let sub_str = %xscan(a bb ccc dddd bb eeeee, %str( ), -2);
%put The value of sub_str = &sub_str;
(注意,我不一定知道这会做你真正想要的,但它会做代码似乎正在做的事情。)
功能式宏的一些提示,由Rob Penridge提供:
答案 1 :(得分:1)
我发布了一个新的答案,因为另一个答案回答了一个稍微不同的问题。
在这里,您的宏实际上是用于执行数据步骤技术,而不是宏技术。您不能(轻松)使用宏来编辑变量内容;宏旨在编写SAS代码,而不是修改变量。您可以使用PROC FCMP
来解决这个问题,如果我有更多的时间,我可能会这样做,但是现在这里只是数据步骤技术和普通(非功能)宏的正确解决方案。
首先,编写数据步骤技术来完成它。这是一个相当混乱但有效的解决方案。它只适用于负start_word_num;如果需要左或右,则需要对循环参数进行一些修改。我建议将此作为起点,并根据您的需求进行改进。
data work.out_data;
set work.in_data;
length sub_str $50;
start_word_num = -(_n_ +1);
do _t = countc(trimn(in_string),' ')+1 to countc(trimn(in_string),' ')+start_word_num+2 by -1;
sub_str = catx(' ',scan(in_string,_t,' '),sub_str);
put _t= sub_str=;
end;
put in_string= sub_str=;
run;
现在,将循环移动到宏中。
%macro xscan(word_num, initial_string, result);
&result.=' ';
do _t = countc(trimn(&initial_string.),' ')+1 to countc(trimn(&initial_string.),' ')+&word_num.+2 by -1;
&result. = catx(' ',scan(&initial_string.,_t,' '),&result.);
end;
%mend xscan;
data work.out_data;
set work.in_data;
length sub_str $50;
start_word_num = -(_n_ +1);
%xscan(start_word_num,in_string,sub_str);
put in_string= sub_str=;
run;