【SAS正則表達式】提取文本數據,分析師小王初上手!| 1. PRXMATCH ()
這是【SAS正則表達式】系列的第一集。
本集目錄:
0. 小王初上手
1. 初始PRXMATCH()
2. metacharater
2.1 什麼是metacharater?
2.2 例子
2.3 metacharater總結
3. 問題解決
3.1 問題重述
3.2 問題理解
3.3 解決代碼
0. 小王初上手
小王畢業了,才剛剛入職,公司為他做了張名片,名片上寫著:
「小王 - 數說國際零售公司 - 數據分析部 - 初級數據分析師」
剛剛畢業的小王,是一位數據分析的新手,在公司里他負責為產品部提供所需的數據,並做分析和決策的輔助。
上班第一周,他就遇到了一個問題,這天,產品部的一個妹子找他來幫忙,問題是這樣的:
資料庫中有一份長長的產品名單,名單中有的是產品的名字,有的是產品的編號,產品部的妹子只想要產品的編號的那些行(下圖下劃線的),以做更深一步的分析。
(01)1872-8756
Body shop P1
Book B13
(05)9212-0098
PD(05)9206-4571
Shushuophone
(12) 6753-5513
None here
PD(12)6434-4532
P&DWashing
......(未顯示完)
紅色字體的編號似乎沒有什麼容易把握的規律:佔位符不一樣、也不全都是數字、有的行的括弧後面還有空格等等,這怎麼提取呢?
你是否在絞盡腦汁的想各種字元串函數、想各種匹配的規則,比如用substr(name,1,1) in (「(「,」P」),這個不行,因為有的非編號的行開頭也可能是P、或者PD等......
可以歇歇了,因為小王只用了1分鐘不到,就把代碼寫好並提取出來了,我們先來看下他的代碼:
a=PRXMATCH("/(dd) ?d{4}-d{4}/", name);
if a GT 0 then output;
結果為:
這代碼是個什麼玩意兒啊?
這些看起來像亂碼的東西就是正則表達式和元字元,下面,我們就從一個函數PRXMATCH()來入手,學習一下如何使用正則表達式。
1. 初識PRXMATCH()
這個函數用來定義一段字元在一句話中的位置,它的格式為:
PRXMATCH ( pattern-id or regular-expression, string )
pattern-id大家先別管,這個函數的作用就是:看regular-expression 在 string 中的位置。
舉個例子:
data _null_;
STRING="I love Shushuo jun";
a=PRXMATCH("/Shu/",STRING);
file print;
put a=;
run;
結果為:
Shu在I love Shushuo jun中的位置是8。
我們來解釋一下 「/Shu/」
這是一個SAS的正則表達式例子,或者說,這是Perl正則表達式的例子,因為SAS里的正則表達就是按照Perl來的。
好吧,有點繞口,您請看下面這個圖:
也就是說,這個雙引號是SAS的語法,但裡面的內容是標準的Perl正則表達式,看到那個斜杠 / 沒有?那是默認的Perl分隔符。
如果您因此認為應該去找一本Perl的書去啃一啃,那就誤會我的意思了,我只是告訴你這個事實而已,您只要關注數說工作室的連載就可以弄明白正則表達式。當然拿一本Perl的書學一學也是極好的。
好了,下面我們就要重點研究一下兩腿之間....哦不,兩個斜杠//之間的秘密,我們可以在兩個斜杠之間放置一些元字元(metacharacter),來簡化一些很複雜的表達。
2. metacharacter
2.1 什麼是metacharacter?
metacharacter用來簡化表達某種意思,比如在word中我們都知道 代表的是製表符,那麼在SAS正則表達式中也類似有:
^代表一段話的開頭,
$代表一段話的結束,
s代表的是一個空格(space)
……
他們就是metacharacter。
很抽象吧?所以我才要結合這個PRAXMATCH來介紹metacharater…
2.2 例子
來看一段代碼:
data _null_;
string1 = "I love Shushuo jun";
string2 = "Shushuo jun loves you";
a = PRXMATCH("/^Shu/",string1);
b = PRXMATCH("/^Shu/",string2);
file print;
put a= b=;
run;
運行結果如下:
所以簡單來說,PRXMATCH(「/^Shu/」,string)匹配的是string的開頭:開頭是Shu,那麼返回1,開頭不是,則返回0。
string1開頭不是Shu,故a返回0,string開頭是Shu,故返回1。
我們學習了 ^ 這個metacharacter,它代表開頭匹配,再學習幾個:
$代表結尾匹配;
i代表不區分大小寫;
d 匹配任何某1個以上數位
ddd 匹配任何某3個以上數位
先對這四個元字元舉例:
data _null_;
string1="I love Shushuo jun";
string2="Shushuo jun loves you";
a=PRXMATCH("/jun$/",string1);
b=PRXMATCH("/jun$/",string2);
c=PRXMATCH("/JUN/i",string1);
d=PRXMATCH("/JUN/",string1);
string3="12";
string4="12a";
string5="122";
string6="1222";
e=PRXMATCH("/ddd/",string3);
f=PRXMATCH("/ddd/",string4);
g=PRXMATCH("/ddd/",string5);
h=PRXMATCH("/ddd/",string6);
file print;
put a= b= c= d= e= f= g= h=;
run;
運行結果為:
解釋:
1)注意$和i的使用位置:」/jun$/」和」/jun/i」,一個在斜杠里,一個在外。
2)a和b中,只有a返回了jun的位置,因為string1中,jun在末尾。
3)c和d中,只有c返回了,因為JUN是大寫,必須用i符號,表示不區分大小寫。
4)e、f返回的是0,因為ddd要求必須至少要有3個數位。所以g、h返回的是1。
2.3 metacharater總結
我們給出一些metacharater總結,供以後使用的時候查詢:
好了,我們現在要開始解釋小王是怎麼解決那個產品列表的問題的了。
3. 問題解決
3.1 問題重述
再重述一遍問題文中最開始的那個問題:
下面是某超市自己的產品列表,有的是編號,有的是產品的名字,我們現在用正則表達式,將產品編號的行(紅色字體的)讀取到SAS數據集中。
Name
(01)1872-8756
Body shop P1
Book B13
(05)9212-0098
PD(05)9206-4571
Shushuophone
(12) 6753-5513
None here
PD(12)6434-4532
P&DWashing
......(未顯示完)
3.2 問題理解
首先我們意義理解一下,我們只要有產品編號的行,產品編號的格式為:
(XX)XXXX-XXXX
但也包括下面的情況:
1)有的編號前面有字母PD,它標誌出過期的產品。
2)有的編號()後面還有一個空格,比如(12) 6753-5513。
綜上所述,正則表達式應該這樣「編碼」:
空格?表示這個空格有或沒有,都被匹配,P?和D?也是同樣道理。因此,提取出編號的正則表達式就應該為:
「/P?D?(dd) ?d{4}-d{4}/」
3.3 解決代碼:
綜上解釋,我們給出小王的代碼:
data production;
input name $char20.;
a=PRXMATCH("/(dd) ?d{4}-d{4}/",name);
if a GT 0 then output;
datalines;
(01)1872-8756
Body shop P1
Book B13
(05)9212-0098
PD(05)9206-4571
Shushuophone
(12) 6753-5513
None here
PD(12)6434-4532
P&DWashing
;
proc print noobs;
title Production ID;
var name;
run;
運行結果為:
這裡為方便解釋,產品名單我們就用顯示出來的那幾個,你可能會說:
產品名單里也許還有其他沒考慮到的情況呢?你的正則表達式一定可靠嗎?
肯定有沒考慮到的情況,所以才有下一集啊。
數說工作室
微信ID:shushuojun
推薦閱讀:
※怎樣優雅地學好 SAS 與 R 語言?
※為什麼只能到99%?
※漫談SAS Macro (3) - Macro Quoting, Part III
※ORDER=DATA in PROC REPORT