使用正则表达式将字符串拆分为多个变量 SAS
Posted
技术标签:
【中文标题】使用正则表达式将字符串拆分为多个变量 SAS【英文标题】:Using regex to split a sting into multiple variables SAS 【发布时间】:2022-01-20 11:14:51 【问题描述】:我对 SAS 中正则表达式的使用有疑问。
我的数据集如下所示:
ID | Code |
---|---|
101 | K2K5K8F10F26F2 |
102 | L7P13P4 |
103 | L1 |
我希望它看起来像这样:
ID | Code |
---|---|
101 | K2 |
101 | K5 |
101 | K8 |
101 | F10 |
101 | F26 |
101 | F2 |
102 | L7 |
102 | P13 |
102 | P4 |
103 | L1 |
一开始我认为先分配新列然后按行更容易。
我的尝试如下:
proc ds2;
data Codes (overwrite=yes);
dcl char(16) code1 code2 code3 code4 code5 code6;
dcl double re;
keep code1 code2 code3 code4 code5 code6;
retain re;
method init();
dcl varchar(32) expression;
expression = '/(\w+\d+)+/';
re=prxparse(expression);
if missing( re ) then do;
put 'ERROR: Invalid expression ' expression;
stop;
end;
end;
method run();
set mytable;
code1 = 'ERROR';
if prxmatch(re, Code) then
do;
code1=prxposn(re, 0, Code);
code2=prxposn(re, 1, Code);
code3=prxposn(re, 2, Code);
code4=prxposn(re, 3, Code);
code5=prxposn(re, 4, Code);
code6=prxposn(re, 5, Code);
end;
else do;
code1='0';
end;
end;
enddata;
run;
quit;
proc print data=Codes;
run;
quit;
但是,没有任何变化。结果,我得到的 code1 和 code2 列与初始数据集中的 Code 列完全一样。我真的很感激这方面的任何帮助,因为正则表达式不是我的强项。我还输入了 code1 = 'ERROR' 和之后的 code1 = '0' 以检查代码是否有效。
需要注意的是,我创建了code6作为试用版。我无法知道每个 ID 的确切代码数量。但是,我确实知道代码必须始终是一个字母和一个或两个数字的组合,它也可以采用 Z12-9 的形式(所以一个字母后跟两个数字,然后是一个破折号,然后是一个数字)。
提前谢谢你!
【问题讨论】:
您使用 PROC DS2 是否有特定原因?这是要求吗?这里的数据步骤相当简单。 这不是必需的,它只是从我使用过的旧代码库中复制而来。但我明白你的意思:) 【参考方案1】:回答这部分的正则表达式,你的正则表达式是错误的,我认为prxposn
可能也是错误的。
\w
匹配数字和 alpha,因此 \w+
将获取所有字符串。您需要使用[A-Z]
,或使用\w+?
以使用不那么激进的匹配来仅获取单个字母后数字集。
另外,这里正确的方法是call prxnext
,prxposn
匹配正则表达式中的每个括号匹配,所以1是第一个,2是第二个,但(something)+
只有是一个括号匹配。 call prxnext
将继续查找单个匹配项的更多匹配项,您可以使用它来获取匹配位。
这里还是简单的数据步骤,但 DS2 类似。
data want;
set have;
rx = prxparse('/[A-Z]+\d+/ios');
start = 1;
do until (pos eq 0);
call prxnext(rx,start,length(code),code,pos,len);
if pos gt 0 then do;
w = substr(code,pos,len);
put w=;
output;
end;
end;
run;
【讨论】:
【参考方案2】:我发现这是call scan
的一个特别好的用例,正则表达式几乎没有那么有效。在这里,我使用call scan
来查找(始终为单个)字母的“单词边界”,然后将其加上下一个字母(或词尾)之前的任何内容。
data have;
length code $20 ;
input id code $;
datalines;
101 K2K5K8F10F26F2
102 L7P13P4
103 L1
;;;;
run;
data want;
set have;
do count = 1 to countw(code,,'a');
call scan(code,count,pos,len,,'a');
w = substr(code,pos-1,len+1);
output;
end;
run;
如果需要的话,我认为这在 DS2 和数据步骤中都可以使用。
【讨论】:
以上是关于使用正则表达式将字符串拆分为多个变量 SAS的主要内容,如果未能解决你的问题,请参考以下文章