假设我有一个宏变量x,它可以包含任意数量的仅字母单词,每个单词由一个或多个空格分隔:
%let x = A B CD ;
我想创建另一个宏变量,在打印时会给出这个结果(单引号也可以换成双引号):
'A','B','CD'
用于in()
声明......即。我要编写看起来像这样的代码:
data want;
set have;
where my_field in ( /* DO SOMETHING TO &X HERE TO GIVE DESIRED OUTPUT */ ) ;
run;
我正在寻找(最好是单行)纯宏代码解决方案。一个不产生这个笔记的:
NOTE 49-169: The meaning of an identifier after a quoted string might change in a
future SAS release. Inserting white space between a quoted string and the succeeding
identifier is recommended.
到目前为止,我有这个:
%let y = %str(%')%sysfunc(tranwrd( %sysfunc(compbl(&x)) ,%str( ),%str(%',%') ))%str(%');
%put &y;
但我无法摆脱那个蠢货。
答案 0 :(得分:3)
对于使用CATS()的FCMP尝试,您需要为结果变量添加LENGTH
语句。 FCMP处理字符变量与数据步骤略有不同。
proc fcmp outlib=work.funcs.funcs;
function delimit_words(iString $) $;
length result $200;
result = cats("'",tranwrd(cats(compbl(iString))," ", "','"),"'");
return (result );
endsub;
run;
options cmplib=work.funcs;
data _null_;
x = " A B C ";
y = delimit_words(x);
put y=;
run;
返回:
5136 data _null_;
5137 x = " A B C ";
5138 y = delimit_words(x);
5139 put y=;
5140 run;
y='A','B','C'
答案 1 :(得分:0)
知道了。诀窍在于添加引号,以确保它们通过插入空格而不与单词边界相邻。所以最初字符串用额外的空格填充。然后在最后,我用compress()
删除了额外的空格。这样我们就可以通过测试来获取引用的字符串标识符!
%let x = A B C ;
%let y = %sysfunc(compress(%str(%' )%sysfunc(tranwrd(%sysfunc(compbl(&x)), %str( ), %str( %',%' ) ))%str( %') ));
%put &y;
结果:
'A','B','C'
虽然有点难看。
编辑:第二次尝试:
以为我会欺骗并使用proc fcmp
。最终结果更好:
proc fcmp outlib=common.funcs.funcs;
function delimit_words(iString $) $;
result = "'" || tranwrd(cats(compbl(iString))," ", "','") || "'";
return (result );
endsub;
run;
Datastep示例:
data x;
x = " A B C ";
y = delimit_words(x);
put y=;
run;
改进的宏示例:
%let x = A B C ;
%let y = %sysfunc(delimit_words(&x));
%put &y;
由于某种原因,如果我尝试使用proc fcmp
函数而不是cats()
连接符,||
给了我意想不到的结果,那么我就去了||
。通过允许用户指定哪个符号构成单词边界,以及是否引用输出,如果是,是否使用单引号或双引号,可以改进该功能......但我会根据需要添加。
答案 2 :(得分:0)
如果您将if条件更改为使用indexw而不是当时我认为您可以完全避免此问题:
data want;
set have;
if indexw("&X",my_field) then do;
output;
end;
run;