正則表達式的功法大全,做NLP再也不怕搞不定字符串了
在自然語言處理中,很多時候我們都需要從文本或字符串中抽取出想要的信息,并進一步做語義理解或其它處理。在本文中,作者由基礎(chǔ)到高級介紹了很多正則表達式,這些表達式或規(guī)則在很多編程語言中都是通用的。
正則表達式(regex 或 regexp)對于從文本中抽取信息極其有用,它一般會搜索匹配特定模式的語句,而這種模式及具體的 ASCII 序列或 Unicode 字符。從解析/替代字符串、預(yù)處理數(shù)據(jù)到網(wǎng)頁爬取,正則表達式的應(yīng)用范圍非常廣。
其中一個比較有意思的地方是,只要我們學(xué)會了正則表達式的語句,我們幾乎可以將其應(yīng)用于多有的編程語言,包括 JavaScript、Python、Ruby 和 Java 等。只不過對于各編程語言所支持的***級特征與語法有細微的區(qū)別。
下面我們可以具體討論一些案例與解釋。
一、基本語句
1. 錨點:^ 和 $
- ^The 匹配任何以“The”開頭的字符串 -> Try it! (https://regex101.com/r/cO8lqs/2)
- end$ 匹配以“end”為結(jié)尾的字符串
- ^The end$ 抽取匹配從“The”開始到“end”結(jié)束的字符串
- roar 匹配任何帶有文本“roar”的字符串
2. 數(shù)量符:*、+、?和 {}
- 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”序列的字符串
3. 或運算符:| 、 []
- a(b|c) 匹配在“a”后面跟著“b”或“c”的字符串 -> Try it! (https://regex101.com/r/cO8lqs/3)
- a[bc] 匹配在“a”后面跟著“b”或“c”的字符串
4. 字符類:\d、\d、\s 和 .
- \d 匹配數(shù)字型的單個字符 -> 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 將執(zhí)行與\d 完全相反的匹配方法:
- \D 匹配單個非數(shù)字型的字符 -> Try it! (https://regex101.com/r/cO8lqs/6)
為了正確地匹配,我們必須使用轉(zhuǎn)義符反斜杠「\」定義我們需要匹配的符號「^.[$()|*+?{\」,因為我們可能認(rèn)為這些符號在原文本中有特殊的含義。
- \$\d 匹配在單個數(shù)字前有符號“$”的字符串 -> Try it! (https://regex101.com/r/cO8lqs/9)
注意我們同樣能匹配 non-printable 字符,例如 Tab 符「\t」、換行符「\n」和回車符「\r」
5. Flags
我們已經(jīng)了解如何構(gòu)建正則表達式,但仍然遺漏了一個非?;A(chǔ)的概念:flags。
正則表達式通常以/abc/這種形式出現(xiàn),其中搜索模式由兩個反斜杠「/」分離。而在模式的結(jié)尾,我們通??梢灾付ㄒ韵?flag 配置或它們的組合:
- g(global)在***次完成匹配后并不會返回結(jié)果,它會繼續(xù)搜索剩下的文本。
- m(multi line)允許使用^和$匹配一行的開始和結(jié)尾,而不是整個序列。
- i(insensitive)令整個表達式不區(qū)分大小寫(例如/aBc/i 將匹配 AbC)。
二、中級語句
1. 分組和捕獲:()
- a(bc) 圓括弧會創(chuàng)建一個捕獲性分組,它會捕獲匹配項“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)
捕獲性圓括號 () 和非捕獲性圓括弧 (?:) 對于從字符串或數(shù)據(jù)中抽取信息非常重要,我們可以使用 Python 等不同的編程語言實現(xiàn)這一功能。從多個分組中捕獲的多個匹配項將以經(jīng)典的數(shù)組形式展示:我們可以使用匹配結(jié)果的索引訪問它們的值。
如果需要為分組添加名稱(使用 (?
2. 方括弧表達式:[]
- [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進制數(shù)字的字符串,不區(qū)分大小寫 -> 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)
記住在方括弧內(nèi),所有特殊字符(包括反斜杠\)都會失去它們應(yīng)有的意義。
3. Greedy 和 Lazy 匹配
數(shù)量符(* + {})是一種貪心運算符,所以它們會遍歷給定的文本,并盡可能匹配。例如,<.+> 可以匹配文本「This is a <div> simple div </div> test」中的「<div>simple div</div>」。為了僅捕獲 div 標(biāo)簽,我們需要使用「?」令貪心搜索變得 Lazy 一點:
- <.+?> 一次或多次匹配 “<” 和 “>” 里面的任何字符,可按需擴展 -> Try it! (https://regex101.com/r/cO8lqs/24)
注意更好的解決方案應(yīng)該需要避免使用「.」,這有利于實現(xiàn)更嚴(yán)格的正則表達式:
- <[^<>]+> 一次或多次匹配 “<” 和 “>” 里面的任何字符,除去 “<” 或 “>” 字符 -> Try it! (https://regex101.com/r/cO8lqs/23)
三、高級語句
1. 邊界符:\b 和 \B
- \babc\b 執(zhí)行整詞匹配搜索 -> Try it! (https://regex101.com/r/cO8lqs/25)
\b 如插入符號那樣表示一個錨點(它與$和^相同)來匹配位置,其中一邊是一個單詞符號(如\w),另一邊不是單詞符號(例如它可能是字符串的起始點或空格符號)。
它同樣能表達相反的非單詞邊界「\B」,它會匹配「\b」不會匹配的位置,如果我們希望找到被單詞字符環(huán)繞的搜索模式,就可以使用它。
- \Babc\B 只要是被單詞字符環(huán)繞的模式就會匹配 -> Try it! (https://regex101.com/r/cO8lqs/26)
2. 前向匹配和后向匹配:(?=) 和 (?<=)
- 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)
四、結(jié)語
正如上文所示,正則表達式的應(yīng)用領(lǐng)域非常廣,很可能各位讀者在開發(fā)的過程中已經(jīng)遇到了它,下面是正則表達式常用的領(lǐng)域:
- 數(shù)據(jù)驗證,例如檢查時間字符串是否符合格式;
- 數(shù)據(jù)抓取,以特定順序抓取包含特定文本或內(nèi)容的網(wǎng)頁;
- 數(shù)據(jù)包裝,將數(shù)據(jù)從某種原格式轉(zhuǎn)換為另外一種格式;
- 字符串解析,例如捕獲所擁有 URL 的 GET 參數(shù),或捕獲一組圓括弧內(nèi)的文本;
- 字符串替代,將字符串中的某個字符替換為其它字符。
原文鏈接:
https://medium.com/factory-mind/regex-tutorial-a-simple-cheatsheet-by-examples-649dc1c3f285
【本文是51CTO專欄機構(gòu)“機器之心”的原創(chuàng)譯文,微信公眾號“機器之心( id: almosthuman2014)”】