iT邦幫忙

2022 iThome 鐵人賽

DAY 3
1
AI & Data

邁向成為語言資料科學家的偉大航道系列 第 3

【NLP】Day 3: 先知道自己想要的是什麼,再開始追尋:正規表達式(1)搜尋

  • 分享至 

  • xImage
  •  

「我赫然發現我一直在追尋著,追尋著我真正想要過的人生。但你知道嗎?我卻竟然完全不知道自己想要什麼樣的人生。
巴尼・史丁森《追愛總動員 How I Met Your Mother》

在進行自然語言處理的同時,常常會需要將資料變得乾淨,或是也有些特定的資料格式要從大量語料中抽取出來,比如說像是地址、電話等等,才有辦法取出我們想要的理想資料,而在這過程中常常會用到的就是正規表達式(regular expression),正規表達式也會被簡稱為re。re可以針對符合的字串大致上分成三種功能:搜尋、替換,以及抽取。

正規表達式

讓我們先以手機號碼舉例,假如我們要從大量語料中抽取手機號碼,例如:0912-345-678,該怎麼做呢?首先,編寫regular expression一個很重要的觀念是要一個字一個字看,並輸入對應的正規表達式。回到手機號碼,我們觀察手機號碼0912-345-678,可以發現全部都是用數字組成,數字的正規表達式為\d,我們首先可以將手機號碼以這種方法表示:

\d\d\d\d-\d\d\d-\d\d\d

但是這樣並不是一個足夠有效率的寫法,若在如\d後面加上大括號,則可以指定其出現次數。我們可以發現以橫槓分隔,第一組是由四個數字,後面則是由兩組三個數字所組成。逗號的分隔方式代表其次數,{1,}為一次以上,{,2}為兩次以下,{1,3}則為一到三次。

\d{4}-\d{3}-\d{3}

但若要取出符合這個樣式的第一組數字的話,則可以透過小括號,將這些數字分組,並在撰寫程式時指定回傳特定組的字串,整串符合的字串為group 0,第一組,四個數字的,也就是group 1,以此類推。寫法如下:

(\d{4})-(\d{3})-(\d{3})

那假如今天要找的是電話號碼,像是(01)234-5678時,裡面有小括號,該怎麼辦才能讓程式知道這裡得括號並不是前述分組的意思?這時我們可以利用逃脫符號\告訴編譯器,這裡的括號是指真的括號,任何會跟正規表達式衝突的符號,都可以透過這種方法進行編寫,寫法如下:

\(\d{2}\)\d{3}-\d{4}

這邊只有介紹到數字的寫法,欲得知其他寫法,如英文字母等等的,可以參考以下這個 cheatsheet,另外若要確認自己寫的正規表達式是否符合的話,也可以運用這個網站 regex101 來進行比對。

搜尋

前面有提到說,regular expression有進行搜尋的功能,我們可以將正規表達式的字串放入函式中,確認資料中是否有我們想要的字段。這時,可以運用re函式庫中的search()來達到我們的目的。第一個參數放正規表達式,第二個參數放欲檢驗的字串。

import re # 記得加入re函式庫
print(re.search("(\d{4})-(\d{3})-(\d{3})", "0987-654-321"))
# output: <re.Match object; span=(0, 12), match='0987-654-321'>

# 輸出的意思是說,若有符合的字串,就會回傳正規表達式的物件
# span則為符合物件的字串在語料中的位置為何,像這邊是整串符合
# 那就是從index = 0 的地方開始到12都是符合的字串。 
# match則是符合的字串。

print(re.search("(\d{4})-(\d{3})-(\d{3})", "0987654321"))
# output: None

# 若沒有符合字串,就會回傳None

# 小應用是,也可以把這個當作條件判斷式的條件之一,例如:

if re.search("(\d{4})-(\d{3})-(\d{3})", "0987-654-321"):
    print(123)
# output: 1234
# 這邊因為re.search()有符合字串,判斷為True,執行指定動作

if re.search("(\d{4})-(\d{3})-(\d{3})", "0987654321"):
    print(456)
# 判斷為False,不進行任何動作

記得前面說的分組概念嗎?在這裡就可以派上用場了。

print(example_re_obj.group(0))

# 你也可以指派一個變數給他,如:
example_re_obj = re.search("(\d{4})-(\d{3})-(\d{3})", "0987-654-321")

# 記得前面說的分組概念嗎?在這裡就可以派上用場了。
print(example_re_obj.group(0))
# output: 0987-654-321
print(example_re_obj.group(1))
# output: 0987
print(example_re_obj.group(2))
# output: 654
print(example_re_obj.group(3))
# output: 321

好的,大概就是這樣,完成了這步驟,接下來就可以往「替換」以及「抽取」的目的地前進了!我們明天見!


上一篇
【NLP】Day 2: 工欲善其事,必先利其器!Python基礎介紹!
下一篇
【NLP】Day 4: 什麼!文本也可以偷天換日?正規表達式 (2) 替換
系列文
邁向成為語言資料科學家的偉大航道30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言