SAS正则表达式
开这个专栏很久了,开栏之后,收到了几个零星的关注;但是,一直没有发表文章。学习开发语言,最好的方式就是去使用,然后根据编程的需求,不断的去完善关于工具的认知。在我进入SAS开发的过程中,总是在碰到问题,然后用技术解决问题:数据读入读出、数值计算、逻辑判断、宏、数组、时间处理、数据格式、正则表达式。
面对脏数据时,往往让开发人员抓狂。在其他开发语言中,比如Python中,可以很方便的使用正则化表达式去提取数据、替换数据。SAS中,正则表达式使用的函数更为复杂,本篇文章,就主要介绍SAS中正则表达式的函数。内容主要参考SAS help文件,见参考资料1。
一.基本函数
| 函数 | 参数 | 返回值 | 说明 |
|---|---|---|---|
| PRXPARSE | regx | regx_id | 以正则式作为输入,输出SAS中指代该正则式的id |
| PRXMATCH | regx/regx_id, string | Integer | 以正则表达式或者正则表达式id以及被匹配对象作为输入,返回首次匹配到的开始位置,匹配失败返回0 |
| PRXPOSN | regx_id, rnk, start, length | 来获取需要的反向匹配结果,输入为4个参数,第一个为正则式id,第二个是反向匹配的序号,第三个和第四个是输出参数,函数执行结束他们会被赋值为反向匹配在原匹配字符串中的位置和长度;这样,利用这两个返回的值并结合substr就可以得到反向匹配字符串 | |
| PRXPOSN | regx_id, rnk, string | 返回子表达式对应的匹配值,注意子表达式含义 | |
| PRXCHANGE | regx/regx_id, oldstring, newstring, length, trunk, num | 替代匹配模式的值 | |
| PRXSUBSTR | regx/regx_id, string, start, length | 返回首次匹配的位置和长度,匹配失败, 则start为0 | |
| PRXNEXT | regx/regx_id, start, stop, string, position, length | 返回多个匹配位置和长度 |
1.PRXMATCH,主要用于查找和匹配,返回匹配到元素在字符串的位置
PRXMATCH("/world/", "Hello world!");
2.PRXCHANGE, 主要用于字符串替换
DATA x;
res = PRXCHANGE("s/world/planet/", 2, "Hello world world world");
RUN;
PROC PRINT; RUN; /* 结果为: Hello planet planet world */
参数含义解释:
- ”s/world/planet/”, 由3部分组成,s指定待替换的元字母, world为正则表达式, planet为新值,即满足正则表达式的内容替换为planet
- 2, 指定替换次数,2表示替换前2次,-1表示全部替换
- “Hello world world world”, 被匹配字符串
二.案例
1. 数据验证 Validating Data
data _null_;
if _N_ = 1 then
do;
paren = "\([2-9]\d\d\) ?[2-9]\d\d-\d\d\d\d";
dash = "[2-9]\d\d-[2-9]\d\d-\d\d\d\d";
expression = "/(" || paren || ")|(" || dash || ")/";
retain re;
re = prxparse(expression);
if missing(re) then
do;
putlog "ERROR: Invalid expression " expression;
stop;
end;
end;
length first last home business $20.;
input first last home business;
if ^prxmatch(re, home) then
putlog "NOTE: Invalid home phone number for " first last home;
if ^prxmatch(re, business) then
putlog "NOTE: Invalid business phone number for " first last business;
datalines;
Jerome Johnson (919)319-1677 (919)846-2198
Romeo Montague 800-899-2164 360-973-6201
Imani Rashid (508)852-2146 (508)366-9821
Palinor Kent . 919-782-3199
Ruby Archuleta . .
Takei Ito 7042982145 .
Tom Joad 209/963/2764 2099-66-8474
;
run;
2. 数据替换 Matching and Replacing Text
在上面,已经简单的叙述了PRXMATCH的用法,SAS Help还给出了PRXMATCH的另一种应用场景,即替换字符串中两个对象的前后顺序,例如英文名中,将FirstName和LastName对换,示例如下:
DATA changeChs;
result1 = PRXCHANGE('s/(\w+), (\w+)/$2 $1/',-1, 'Jones, Fred');
result2 = PRXCHANGE("s/(MC)/\u\L$1/i", -1, "MCLAUNCE");
RUN;
PROC PRINT; RUN;
/*
输出:Fred Jones McLAUNCE
*/
3. 数据提取 Extracting a Substring from a String
DATA old;
FORMAT name $100.;
name="一"; OUTPUT;
name="SHA256 56"; OUTPUT;
RUN;
DATA zhengze;
SET old;
re1 = PRXPARSE("/[A-Za-z0-9]+/");
id3=PRXMATCH(re1,name);
CALL PRXSUBSTR(re1,name,start,length);
IF length GT 0 THEN DO;
number=SUBSTR(name,start,length); OUTPUT;
END;
KEEP
number
;
RUN;
PROC PRINT; RUN;
4. 穷举字符串的匹配子串 - PRENEXT
直接使用SAS help上面的例子 ```SAS DATA NULL; regx = PRXPARSE(‘/[crb]at/’); text = “The woods has a bat, cat and rat!”;
start = 1;
stop = LENGTH(text);
/*
Use PRXNEXT to find the first instance of the pattern
then use do while to find all further instance
PRXNEXT changes the start parameter so that searching
begins again after the last match
*/
CALL PRXNEXT(regx, start, stop, text, position, length);
DO WHILE(position>0);
fnd = SUBSTR(text, position, length);
PUT fnd= position= length=;
CALL PRXNEXT(regx, start, stop, text, position, length);
END; RUN; ```
三.Perl Regx
以上,开门见山的介绍了,SAS中的正则表达式函数以及几个典型的应用场景。在我们的工作中,面对的数据清洗需求不一,所以,有必要详细的了解Perl Regx(元字母含义、子表达式等),请参阅文献2。
总结
本文主要讲述了PREMATCH、PRECHANGE、PRESUBSTR的使用方法,对于一般的数据清理工作,这三个正则表达式基本可以满足。其他函数的使用,如有必要,以后再做补充。
参考文献
- SAS help, Using Perl Regular Expressions in the DATA Step
- Tables of Perl Regular Expression (PRX) Metacharacters