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

SAS:提取ID';从文本字符串中用破折号分隔的,sas,delimiter,Sas,Delimiter,我有一个数据集,它有一个连接的文本字段。我试图在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;

我有一个数据集,它有一个连接的文本字段。我试图在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 &$64.;
   cards;
MAY12-KANSAS-ABCD6194-XY7199-BRULE
JAN32-OHIO-BZ5752-GARY
;
run;
data need;
   length id $16;
   set have;
   date = scan(var1,1,'-','o');
   state = scan(var1,2,'-','o');
   id = scan(var1,3,'-','');
run;

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

详细文档可在此处找到:

我建议你从这篇论文开始:

如果您从未接触过那些PRX函数,那么对代码的直接解释可能会让您更加困惑

data have;
    input Var1 &$64.;
    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是偏移量“-”

\u infle\umagic
是此项的搜索词。基本上,我们使用
\u infle\u
自动变量(包含当前从输入文件读入的行)来利用简单的语法进行输入

*Create a dataset with your data;
data have;
  length var1 $100;
  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 $5
    state $20
    id $50
  ;                 *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.;

注意,这只适用于嵌入的分隔符出现在行的末尾。如果他们在中间,这个方法就不起作用了,你必须使用一种不同的方法(比如正则表达式),或者告诉任何人给你一个以这种方式格式化的文件,以更有用的方式给你,即不使用数据中的定界符。.

获取包含单词的多分隔符的另一种不同方法是使用。它将告诉你第n个单词的位置(和长度,我们忽略它)(可以向前或向后,这样可以给你一些在字符串中间搜索的能力)。 针对这种特殊情况实施,非常简单:

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

位置
长度
调用扫描
填充值的变量,我们可以使用这些值。(我们也可以这样做日期和状态,但这比使用函数要复杂。)

使用tranwrd删除日期和状态

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

谢谢你的帮助。我不熟悉PRXCHANGE函数,所以在代码中很难操作它。您建议的代码是“ABCD6194-XY7199-”而不是“ABCD6194-XY7199-BRULE”。我将如何修改函数以获得字符串的最后一个“BRULE”片段?@Haikoubian您可能需要解释正则表达式中的逻辑,即解释它正在搜索的模式,以帮助Ryan了解它是如何工作的。这可能是一个长度问题。在数据步骤的开头添加一个长度语句:data-want;集有;长度id$100/*大到足以容纳尽可能长的ID*/@Haikoubian StackOverflow更喜欢“教人钓鱼”的方法-请始终解释您的代码在做什么以及该方法是什么,甚至优先于提供任何代码。@Haikoubian感谢您添加这一点。请为第一部分添加直接解释-一些简单的东西就足够了,比如“这里我们用PRX删除前两部分,其余部分是ID”。链接到函数文档比简单地解释你正在做的事情背后的原因更重要。你在第二段中所做的是完美的(虽然我不会像那样使用斜体字,但读起来有点难)。