天天看點

Python每日一庫之re

作者:喜歡編碼的社畜
Python每日一庫之re

什麼是正規表達式?

正規表達式(稱為 RE、或正規表達式或正規表達式模式)本質上是一種嵌入 Python 中并通過 re 子產品提供的小型、高度專業化的程式設計語言。使用這種語言,我們可以為我們想要比對的一組可能的字元串指定規則;這個集合可能包含字元串、電子郵件位址或任何你喜歡的東西。

正規表達式文法

正規表達式(或 RE)指定一組與其比對的字元串;這個子產品中的函數讓你檢查一個特定的字元串是否比對一個給定的正規表達式(或者一個給定的正規表達式是否比對一個特定的字元串,這歸結為同一件事)。

正規表達式的特殊字元表格

特殊字元 語義 示例
. 比對包括換行符在内的任何字元 .ab
^ 比對字元串的開頭,并且在 多行模式下,每個換行符之後也立即比對 ^ab
$ 比對字元串末尾或字元串末尾換行符之前,并且在多行模式下也比對換行符之前 ab$
* 比對前面的RE 0次或更多次重複,盡可能多的重複 ab*,ab* 将比對“ a”、“ ab”或“ a”後面跟任意數量的“ b”
+ 比對前面的RE1個或多個重複 ab+,将比對“ a”後跟任意非零數的“ b”
? 比對前面 RE 的0或1次重複 ab?,ab?将比對“ a”或“ ab”
*?, +?, ?? “ *”,“ +”,還有“ ?”修飾符都是貪婪的; 它們盡可能比對更多的文本。有時這種行為是不需要的; 如果 RE < . * > 與“ < a > b < c >”比對,則它将比對整個字元串,而不僅僅是“ < a >”。增加?在限定符使其以非貪婪或最小方式執行比對之後; 将比對盡可能少的字元。使用 RE < .*?>将隻比對“ < a >”。 <.*?>,<.*>
{m} 指定正好比對前一個 RE 的 m 個副本; 比對次數越少,則整個 RE 不比對 {6}将正好比對6個“ a”字元,但不比對5個。
{m,n} 擴充前一個字元m至n次(含n) ab{1,2}c 表示abc、abbc
{m,n}? 使得到的RE比對前一個RE的m到n次重複,嘗試比對盡可能少的重複.這是前一個限定符的非貪婪版本 {3,5}将比對5個'a'字元,而{3,5}?隻會比對3個字元
\ 轉義特殊字元 \?
[] 用于表示一組字元 [abc],将比對”a“、”b”、“c”,也可以表示字元範圍[0-9],[a-z],[A-Z],還可以通過補集來比對例如[^5]将比對除5以外的任何字元。
| 左右表達式任意一個 abc|def 比對abc,def
\d 比對數字0-9 \d
\D 比對任何(非數字)不是十進制數字的字元跟\d相反 \D,相當于[^0-9]
\s 比對 Unicode 空白字元(包括 [ \t\n\r\f\v],以及許多其他字元、空白(制表符、空格、換行符等) \s
\S 比對任何不是空白字元的字元與\s相反 \S相當于[^\t\n\r\f\v]
\w 比對 Unicode 單詞字元;這包括可以成為任何語言中單詞一部分的大多數字元,以及數字和下劃線 \w相當于[a-zA-Z0-9_]
\W 比對任何不是單詞字元的字元與 \w 正好相反 \W相當于[^a-zA-Z0-9_]
\A 僅比對字元串的開頭 \A
\Z 僅比對字元串的末尾 \Z
\b 比對空字元串,但隻比對單詞的開頭或結尾 \b
\B 比對空字元串,但僅當它不在單詞的開頭或結尾時。\B 與 \b 正好相反 \B

在Python中使用RE子產品

  • 導入子產品
import re           
  • re.search():Search (pattern,string,Flag = 0),在字元串中搜尋正規表達式模式生成比對的第一個位置,并傳回相應的比對對象。如果字元串中沒有位置與模式比對,則傳回 Nothing; 請注意,這與在字元串中的某個位置查找零長度比對不同

search方法代碼示例:

Python每日一庫之re

Start ()和 end ()方法為字元串提供索引,顯示模式比對的文本出現的位置,group()方法輸出比對的文本。

Python每日一庫之re
  • re.match():re.match(pattern, string, flags=0),如果字元串開頭的零個或多個字元與正規表達式模式比對,則傳回相應的比對對象。如果字元串與模式不比對,則傳回 None;請注意,這與零長度比對不同。Python 中 re 的 re.match() 函數将搜尋正規表達式模式并傳回第一個比對項。Python RegEx Match 方法僅在字元串的開頭檢查比對項。是以,如果在第一行找到比對項,則傳回比對對象。但如果在其他行中找到比對項,Python RegEx Match 函數将傳回 None。

match()方法代碼示例:

Python每日一庫之re

為啥match方法傳回None?是因為字元串"Python"沒出現在文本的開頭,使用 match() 找不到。

我們改一下代碼來看看

Python每日一庫之re

現在比對到了字元串,因為字元串"Jack"位于字元串的開頭。

  • re.fullmatch():re.fullmatch(pattern, string, flags=0) ,如果整個字元串與正規表達式模式比對,則傳回相應的比對對象。如果字元串與模式不比對,則傳回 None;請注意,這與零長度比對不同。

fullmatch()方法代碼示例:

Python每日一庫之re

為啥fullmatch()傳回了None?因為fullmatch是整個字元串與正規表達式比對,上面的代碼隻比對了字元串“Jack”,是以傳回None。

我們改一下代碼來看看

Python每日一庫之re
  • re.findall()方法:re.findall(pattern, string, flags=0) ,傳回字元串中模式的所有非重疊比對,作為字元串或元組的清單。從左到右掃描字元串,并按找到的順序傳回比對項。結果中包含空比對項。

    結果取決于模式中捕獲組的數量。如果沒有組,則傳回與整個模式比對的字元串清單。如果隻有一個組,則傳回與該組比對的字元串清單。如果存在多個組,則傳回與組比對的字元串元組清單。非捕獲組不影響結果的形式。

findall()方法代碼示例:

Python每日一庫之re

使用正規表達式來比對文本。

#\b - Matches the empty string, but only at the beginning or end of a word.
#M - It should match 'M'
#[a-z] - set of character from a to z
#* - It should be zero or more 
pattern = r'\bM[a-z]*'
text = 'Data Science is forcing every business to act differently. The decision making today is far more \
complex and driven by AI and Machine Learning Models. The Business Intelligence tools of yesterday are being rewritten to incorporate Data Science and Machine Learning.'
re.findall(pattern, text)           
Python每日一庫之re
  • re.finditer():re.finditer(pattern, string, flags=0) ,傳回一個疊代器,在字元串中的 RE 模式的所有非重疊比對中産生比對對象。從左到右掃描字元串,并按找到的順序傳回比對項。結果中包含空比對項。finditer() 函數傳回一個生成 Match 執行個體的疊代器,而不是 findall() 傳回的字元串。

finditer()方法代碼示例:

pattern = 'Machine Learning'
text = 'Data Science is forcing every business to act differently. The decision making today is far more \
complex and driven by AI and Machine Learning Models. The Business Intelligence tools of yesterday are being rewritten to incorporate Data Science and Machine Learning.'
for match in re.finditer(pattern, text):
    s = match.start()
    e = match.end()
    print('Found "{}" \n from {} to {} ("{}")'.format(pattern, s, e, text[s:e]))           
Python每日一庫之re
  • re.compile():re.compile(pattern, flags=0) ,将正規表達式模式編譯成正規表達式對象,可以使用它的 match()、search() 和其他方法進行比對。

compile()方法代碼示例:

import re
ore = re.compile(r'\d{4}')
a = ['1234','abc123','123bgt4567','qwer1234']
for it in a:
  if ore.search(it):
     print(it)

# output 
# 1234
# 123bgt4567
# qwer1234           

這裡注意一個問題就是:當我們需要一個正規表達式比對多個文本我們使用compile來編譯正規表達式然後利用for循環來做比對看起來非常便捷,但是其實其它re的一些方法自帶compile,根本沒有必要多此一舉先re.compile再調用正規表達式方法,是以一般來說除非特别需求不然不建議使用re.compile。

  • re.sub():re.sub(pattern, repl, string, count=0, flags=0) ,傳回通過替換 repl 替換 string 中最左邊的不重疊出現的模式獲得的字元串。如果未找到該模式,則字元串原封不動地傳回。repl 可以是字元串或函數;如果它是一個字元串,則處理其中的任何反斜杠轉義。也就是說,\n 轉換為單個換行符,\r 轉換為回車符,等等。ASCII 字母的未知轉義保留供将來使用并視為錯誤。其他未知的轉義例如 \& 被單獨留下。反向引用,例如 \6,被替換為模式中第 6 組比對的子字元串。
Python每日一庫之re
  • re.subn():re.subn(pattern, repl, string, count=0, flags=0) ,執行與 sub() 相同的操作,但傳回一個元組 (new_string, number_of_subs_made)。意味着傳回新字元串以及替換次數。
# Importing re module
import re

# Given String
s = "I am a human being."

# Performing the subn() operation
res_1 = re.subn('a', 'x', s)
res_2 = re.subn('[a,I]','x',s)

# Print Results
print(res_1)
print(res_2)           
Python每日一庫之re
  • 常用的一些正則比對
'ab*', - a 後跟零個或多個 b 
'ab+', - a 後跟一個或多個 b 
'ab?', - a 後跟零或一個 b 
'ab{3}' - a 後跟三個 b 
'ab{2,3}' - a 後跟兩到三個 b 
'ab*?' - a 後跟零個或多個 b 
'ab+?' - a 後跟一個或多個 b 
'ab??' - a 後跟零或一個 b 
'ab{3}?' - a 後跟三個 b 
'ab{2,3}?' - a 後接兩到三個 b 
'[ab]' - a 或 b 
'a[ab]+' - a 後接一個或多個 a 或 b 
'a[ab]+?' - a 後跟一個或多個 a 或 b,不是貪婪的 
'[a-z]+' - 小寫字母序列
'[A-Z]+' - 大寫字母序列
'[a-zA-Z]+' - 小寫或大寫字母序列
'[A-Z][a-z]+' - 一個大寫字母後跟小寫字母
'a.' - a 後跟任意一個字元
'b.' - b 後接任意一個字元
'a.*b' - a 後接任意字元,以 b 結尾
'a.*?b' - a 後接任意字元,以 b 結尾
r'\d+' - 數字序列
r'\ D+' - 非數字序列
r'\s+' - 空白序列
r'\S+' - 非空白序列
r'\w+' - 字母數字字元
r'\W+' - 非字母數字
'[^-. ]+' - 不帶 -、. 或空格的序列           
下一期我将分享Python Beautiful Soup庫的使用方法,喜歡爬蟲的應該喜歡這個第三方庫,如果對我的文章感興趣可以關注我,如果有想了解的Python庫也可以在評論留言,我将采納你們的意見寫相關的文章。