在SAS中动态连接变量

在SAS中动态连接变量,sas,append,concatenation,do-loops,Sas,Append,Concatenation,Do Loops,我想创建一个变量,该变量解析为字符串中指定字符*之前的字符。但是我现在问自己,如果这个指定的字符在一个字符串中多次出现,就像下面的示例中一样,如何检索一个变量,该变量将所有出现的字符连接起来,然后用逗号分隔 例如: data have; infile datalines delimiter=","; input string :$20.; datalines; ABC*EDE*, EFCC*W*d* ; run; data have; infile datalines de

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

例如:

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

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


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

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

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

data want;
  set have;
  length before $20 ;
  _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

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

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

data want;
  set have;
  length before $20 ;
  _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 :$20.;
datalines;
ABC*EDE*,
EFCC*W*d*
;
run;
data have;
infile datalines delimiter=",";
input string :$20.;
datalines;
ABC*EDE*,
EFCC*W*d*
;

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

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

例如:

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

data want;
  set have;
  csl = prxchange('s/([^*]*?)([^*])\*/$2,/',-1,string);  /* comma separated letters */
  csl = prxchange('s/, *$//',1,csl);                     /* remove trailing comma */
run;
呼叫扫描也是获取每个*位置的好选择

结果:

_N_=1        before=C,E
_N_=2        before=C,W,d
_N_=3        before=
_N_=4        before=
呼叫扫描也是获取每个*位置的好选择

结果:

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

非常感谢。我刚刚意识到你可以做var1=catsvar1,…catsa,“,”,b和catx,“,”,a,b之间的区别是当a或b只有空格时会发生什么。你可以通过初始值1避免=:“*”情况。谢谢!我刚刚意识到你可以做var1=catsvar1,…catsa,“,”,b和catx,“,”,a,b之间的区别是当a或b只有空格时会发生什么。你可以通过初始的_startpos为1来避免=:“*”情况。