SAS:从文本字符串中提取用破折号分隔的 ID

SAS: Extract ID's separated by dashes from text string

我有一个包含一个串联文本字段的数据集。我试图在 SAS 9.4 中将其分成三个文本列。

Obs Var1
1   MAY12-KANSAS-ABCD6194-XY7199-BRULE
2   JAN32-OHIO-BZ5752-GARY

观察 1 的输出应如下所示:

Obs   Date   State   ID
1     MAY12  KANSAS  ABCD6194-XY7199-BRULE

这是我所拥有的,适用于日期和州。但是,我无法让第三部分(ID)忽略分隔符:

data have;
   input Var1 &.;
   cards;
MAY12-KANSAS-ABCD6194-XY7199-BRULE
JAN32-OHIO-BZ5752-GARY
;
run;
data need;
   length id ;
   set have;
   date = scan(var1,1,'-','o');
   state = scan(var1,2,'-','o');
   id = scan(var1,3,'-','');
run;

正则表达式可能是一个选项

可以在这里找到详细的文档:http://support.sas.com/documentation/cdl/en/lefunctionsref/67398/HTML/default/viewer.htm#n0r8h2fa8djqf1n1cnenrvm573br.htm

我建议您从本文开始:http://www2.sas.com/proceedings/sugi29/265-29.pdf

如果您从未接触过那些 PRX 函数,直接对代码进行解释甚至会使您更加困惑。

data have;
    input Var1 &.;
    cards;
MAY12-KANSAS-ABCD6194-XY7199-BRULE
JAN32-OHIO-BZ5752-GARY
;
run;

data want;
    set have;
    date=scan(var1,1);
    state=scan(var1,2);
    id=prxchange('s/^\w+-\w+-//',1,var1);
run;

或者作为对现有代码的简单修复:

data want;
    set have;
    date=scan(var1,1);
    state=scan(var1,2);
/*  id=prxchange('s/^\w+-\w+-//',1,var1);*/
    id=substr(var1,length(cats(date,state))+3);
run;

由长度函数开始的表达式将给出提取您感兴趣的字符串的起点。 Length + Cats 函数将给出日期和状态的总长度,+3 是偏移'-'。

_INFILE_ Magic 是这个的搜索词。基本上,我们使用 _infile_ 自动变量(包含当前从输入文件中读入的行)来利用简单的输入语法。

*Create a dataset with your data;
data have;
  length var1 0;
  input var1 $;
datalines;
MAY12-KANSAS-ABCD6194-XY7199-BRULE
JAN32-OHIO-BZ5752-GARY
;;;;
run;

data want;
  infile cards dlm='-';  *cards=datalines=in-line data, just used to get something blank to pretend to read from;
  length
    date 
    state 
    id 
  ;                 *set up lengths for your variables;
  set have;         *Now read in your dataset;
  input @1 @@;      *Start the input pointer at the beginning of the imaginary line and do not advance lines ever (since we have no lines!);
  _infile_=var1;    *Assign the contents of var1 to _infile_, so now we have a line;
  input
    date $
    state $
    id $ & @@
    ;               *Input using normal input techniques.  & tells it to read the rest of that line into the id variable (even the dashes), and @@ says stay on this line still (since we have more rows).
  cards;

run;                *Note we do not really have any cards/datalines.;

请注意,这仅适用于您的嵌入式定界符出现在行尾。如果他们在行的中间,这种方法将不起作用,您将不得不使用不同的方法(例如正则表达式,或者告诉给您以这种方式格式化的文件的任何人以更详细的方式将其提供给您有用的方式,即不使用数据中也存在的定界符)。

获取包含多定界符的单词的另一种不同方法是使用 call scan。它会告诉你第 n 个单词的位置(和长度,我们忽略)(可以向前或向后,所以这给了你一些在字符串中间搜索的能力)。

针对这种特殊情况实施非常简单:

data want;
  set have;
  length 
    date 
    state 
    id 
  ;
  date = scan(var1,1);
  state= scan(var1,2);
  call scan(var1,3,position,length);
  id = substr(var1,position);
run;

positionlengthcall scan 填充我们可以使用的值的变量。 (我们也可以用这种方式完成日期和状态,但它比使用该函数更有效。)

使用 tranwrd 删除日期和状态。

data want;
  set have;
  length 
    date 
    state 
    id 
  ;
  date = scan(var1,1);
  state= scan(var1,2);
  id= tranwrd(var1,cats(date,'-',state,'-'),'');
run;