在SAS中动态连接变量

Concatenating a variable dynamically in SAS

我想创建一个变量来解析字符串中指定字符 (*) 之前的字符。但是我现在问自己,如果这个指定的字符在一个字符串中出现多次(如下例所示),如何检索一个变量,该变量连接之前出现的所有字符,用逗号分隔?

示例:

data have;
infile datalines delimiter=",";
input string :.;
datalines;
ABC*EDE*,
EFCC*W*d*
;
run;

代码:

data want;
    set have;
    cnt = count(string, "*");
    _startpos = 0;

    do i=0 to cnt until(_startpos=0); 
        before = catx(",",substr(string, find(string, "*", _startpos+1)-1,1));
    end;    
    drop i _startpos;
run;

第一次和第二次观察的代码输出 before=C。但是,我希望第一个观察结果为 before=C,E,第二次观察结果为 before=C,W,d

确保递增 _STARTPOS 以便您的循环结束。您可以使用 CATX() 添加逗号。使用 CHAR() 而不是 SUBSTR() 来简化选择字符。还要确保告诉数据步骤如何定义新变量,而不是强迫它猜测。我还包括测试来处理 * 处于第一个位置的情况。

data have;
  input string .;
datalines;
ABC*EDE*
EFCC*W*d*
*XXXX*
asdf
;

data want;
  set have;
  length before  ;
  _startpos = 0;
  do cnt=0 to length(string) until(_startpos=0); 
    _startpos = find(string,'*',_startpos+1);
    if _startpos>1 then before = catx(',',before,char(string,_startpos-1));
  end;    
  cnt=cnt-(string=:'*');
  drop i _startpos;
run;

结果:

Obs    string       before    cnt

 1     ABC*EDE*     C,E        2
 2     EFCC*W*d*    C,W,d      3
 3     *XXXX*       X          1
 4     asdf                    0

您可以使用 Perl 正则表达式替换模式来转换原始字符串。

示例:

data have;
infile datalines delimiter=",";
input string :.;
datalines;
ABC*EDE*,
EFCC*W*d*
;

data want;
  set have;
  csl = prxchange('s/([^*]*?)([^*])\*/,/',-1,string);  /* comma separated letters */
  csl = prxchange('s/, *$//',1,csl);                     /* remove trailing comma */
run;

call scan 也是获得每个 *.

位置的好选择
data have;
infile datalines delimiter=",";
input string :.;
datalines;
ABC*EDE*,
EFCC*W*d*
****
asdf
;

data want;
  length before .;
  set have;

  do i = 1 to count(string,'*');
    call scan(string,i,pos,len,'*');
    before = catx(',',before,substrn(string,pos+len-1,1));
  end;
  put _n_ = +7 before=;
run;

结果:

_N_=1        before=C,E
_N_=2        before=C,W,d
_N_=3        before=
_N_=4        before=