【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

TAG:SAS | 正则表达式 | 文本分析 |