正則表達式的功法大全,作NLP不再怕搞不定字符串了

選自Medium,做者:Jonny Fox,機器之心編譯。正則表達式

在天然語言處理中,不少時候咱們都須要從文本或字符串中抽取出想要的信息,並進一步作語義理解或其它處理。在本文中,做者由基礎到高級介紹了不少正則表達式,這些表達式或規則在不少編程語言中都是通用的。編程

正則表達式(regex 或 regexp)對於從文本中抽取信息極其有用,它通常會搜索匹配特定模式的語句,而這種模式及具體的 ASCII 序列或 Unicode 字符。從解析/替代字符串、預處理數據到網頁爬取,正則表達式的應用範圍很是廣。數組

其中一個比較有意思的地方是,只要咱們學會了正則表達式的語句,咱們幾乎能夠將其應用於多有的編程語言,包括 JavaScript、Python、Ruby 和 Java 等。只不過對於各編程語言所支持的最高級特徵與語法有細微的區別。bash

下面咱們能夠具體討論一些案例與解釋。編程語言

基本語句

錨點:^ 和 $spa

^The        匹配任何以「The」開頭的字符串 -> Try it! (https://regex101.com/r/cO8lqs/2)
end$        匹配以「end」爲結尾的字符串
^The end$   抽取匹配從「The」開始到「end」結束的字符串
roar        匹配任何帶有文本「roar」的字符串複製代碼

數量符:*、+、?和 {}code

abc*        匹配在「ab」後面跟着零個或多個「c」的字符串 -> Try it! (https://regex101.com/r/cO8lqs/1)
abc+        匹配在「ab」後面跟着一個或多個「c」的字符串
abc?        匹配在「ab」後面跟着零個或一個「c」的字符串
abc{2}      匹配在「ab」後面跟着兩個「c」的字符串
abc{2,}     匹配在「ab」後面跟着兩個或更多「c」的字符串
abc{2,5}    匹配在「ab」後面跟着2到5個「c」的字符串
a(bc)*      匹配在「a」後面跟着零個或更多「bc」序列的字符串
a(bc){2,5}  匹配在「a」後面跟着2到5個「bc」序列的字符串複製代碼

或運算符:| 、 []regexp

a(b|c)     匹配在「a」後面跟着「b」或「c」的字符串 -> Try it! (https://regex101.com/r/cO8lqs/3)
a[bc]      匹配在「a」後面跟着「b」或「c」的字符串複製代碼

字符類:\d、\d、\s 和 .orm

\d         匹配數字型的單個字符 -> Try it! (https://regex101.com/r/cO8lqs/4)
\w         匹配單個詞字(字母加下劃線) -> Try it! (https://regex101.com/r/cO8lqs/4)
\s         匹配單個空格字符(包括製表符和換行符) 
.          匹配任意字符 -> Try it! (https://regex101.com/r/cO8lqs/5)複製代碼

使用「.」運算符須要很是當心,由於常見類或排除型字符類都要更快與精確。\d、\w 和\s 一樣有它們各自的排除型字符類,即\D、\W 和\S。例如\D 將執行與\d 徹底相反的匹配方法:cdn

\D         匹配單個非數字型的字符 -> Try it! (https://regex101.com/r/cO8lqs/6)複製代碼

爲了正確地匹配,咱們必須使用轉義符反斜槓「\」定義咱們須要匹配的符號「^.[$()|*+?{\」,由於咱們可能認爲這些符號在原文本中有特殊的含義。

\$\d       匹配在單個數字前有符號「$」的字符串 -> Try it! (https://regex101.com/r/cO8lqs/9)複製代碼

注意咱們一樣能匹配 non-printable 字符,例如 Tab 符「\t」、換行符「\n」和回車符「\r」

Flags

咱們已經瞭解如何構建正則表達式,但仍然遺漏了一個很是基礎的概念:flags。

正則表達式一般以/abc/這種形式出現,其中搜索模式由兩個反斜槓「/」分離。而在模式的結尾,咱們一般能夠指定如下 flag 配置或它們的組合:

  • g(global)在第一次完成匹配後並不會返回結果,它會繼續搜索剩下的文本。

  • m(multi line)容許使用^和$匹配一行的開始和結尾,而不是整個序列。

  • i(insensitive)令整個表達式不區分大小寫(例如/aBc/i 將匹配 AbC)。

中級語句

分組和捕獲:()

a(bc)           圓括弧會建立一個捕獲性分組,它會捕獲匹配項「bc」 -> Try it! (https://regex101.com/r/cO8lqs/11)
a(?:bc)*        使用 「?:」 會使捕獲分組失效,只須要匹配前面的「a」 -> Try it! (https://regex101.com/r/cO8lqs/12)
a(?<foo>bc)     使用 「?<foo>」 會爲分組配置一個名稱 -> Try it! (https://regex101.com/r/cO8lqs/17)複製代碼

捕獲性圓括號 () 和非捕獲性圓括弧 (?:) 對於從字符串或數據中抽取信息很是重要,咱們可使用 Python 等不一樣的編程語言實現這一功能。從多個分組中捕獲的多個匹配項將以經典的數組形式展現:咱們可使用匹配結果的索引訪問它們的值。

若是須要爲分組添加名稱(使用 (?<foo>...)),咱們就能如字典那樣使用匹配結果檢索分組的值,其中字典的鍵爲分組的名稱。

方括弧表達式:[]

[abc]            匹配帶有一個「a」、「ab」或「ac」的字符串 -> 與 a|b|c 同樣 -> Try it! (https://regex101.com/r/cO8lqs/7)
[a-c]            匹配帶有一個「a」、「ab」或「ac」的字符串 -> 與 a|b|c 同樣
[a-fA-F0-9]      匹配一個表明16進制數字的字符串,不區分大小寫 -> Try it! (https://regex101.com/r/cO8lqs/22)
[0-9]%           匹配在%符號前面帶有0到9這幾個字符的字符串
[^a-zA-Z]        匹配不帶a到z或A到Z的字符串,其中^爲否認表達式 -> Try it! (https://regex101.com/r/cO8lqs/10)複製代碼

記住在方括弧內,全部特殊字符(包括反斜槓\)都會失去它們應有的意義。

Greedy 和 Lazy 匹配

數量符(* + {})是一種貪心運算符,因此它們會遍歷給定的文本,並儘量匹配。例如,<.+> 能夠匹配文本「This is a <div> simple div</div> test」中的「<div>simple div</div>」。爲了僅捕獲 div 標籤,咱們須要使用「?」令貪心搜索變得 Lazy 一點:

<.+?>            一次或屢次匹配 「<」 和 「>」 裏面的任何字符,可按需擴展 -> Try it! (https://regex101.com/r/cO8lqs/24)複製代碼

注意更好的解決方案應該須要避免使用「.」,這有利於實現更嚴格的正則表達式:

<[^<>]+>         一次或屢次匹配 「<」 和 「>」 裏面的任何字符,除去 「<」 或 「>」 字符 -> Try it! (https://regex101.com/r/cO8lqs/23)複製代碼

高級語句

邊界符:\b 和 \B

\babc\b          執行整詞匹配搜索 -> Try it! (https://regex101.com/r/cO8lqs/25)複製代碼

\b 如插入符號那樣表示一個錨點(它與$和^相同)來匹配位置,其中一邊是一個單詞符號(如\w),另外一邊不是單詞符號(例如它多是字符串的起始點或空格符號)。

它一樣能表達相反的非單詞邊界「\B」,它會匹配「\b」不會匹配的位置,若是咱們但願找到被單詞字符環繞的搜索模式,就可使用它。

\Babc\B          只要是被單詞字符環繞的模式就會匹配 -> Try it! (https://regex101.com/r/cO8lqs/26)複製代碼

前向匹配和後向匹配:(?=) 和 (?<=)

d(?=r)       只有在後面跟着「r」的時候才匹配「d」,可是「r」並不會成爲整個正則表達式匹配的一部分 -> Try it! (https://regex101.com/r/cO8lqs/18)
(?<=r)d      只有在前面跟着「r」時才匹配「d」,可是「r」並不會成爲整個正則表達式匹配的一部分 -> Try it! (https://regex101.com/r/cO8lqs/19)複製代碼

咱們一樣能使用否認運算子:

d(?!r)       只有在後面不跟着「r」的時候才匹配「d」,可是「r」並不會成爲整個正則表達式匹配的一部分 -> Try it! (https://regex101.com/r/cO8lqs/20)
(?<!r)d      只有在前面不跟着「r」時才匹配「d」,可是「r」並不會成爲整個正則表達式匹配的一部分* *->* **Try it!* (https://regex101.com/r/cO8lqs/21)複製代碼

結語

正如上文所示,正則表達式的應用領域很是廣,極可能各位讀者在開發的過程當中已經遇到了它,下面是正則表達式經常使用的領域:

  • 數據驗證,例如檢查時間字符串是否符合格式;

  • 數據抓取,以特定順序抓取包含特定文本或內容的網頁;

  • 數據包裝,將數據從某種原格式轉換爲另一種格式;

  • 字符串解析,例如捕獲所擁有 URL 的 GET 參數,或捕獲一組圓括弧內的文本;

  • 字符串替代,將字符串中的某個字符替換爲其它字符。

原文連接:medium.com/factory-min…

相關文章
相關標籤/搜索