在SAS宏变量中分隔单词

时间:2014-04-18 01:06:39

标签: macros sas delimiter

假设我有一个宏变量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;

但我无法摆脱那个蠢货。

3 个答案:

答案 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;