正則表達式

正則表達式(稱為RE,或正則,或正則表達式模式)本質(zhì)上是嵌入在Python中的一種微小的、高度專業(yè)化的編程語言,可通過 re 模塊獲得。

簡單模式

正則表達式用于對字符串進行操作,因此我們將從最常見的任務開始:匹配字符

匹配字符:匹配不同的字符集合是正則表達式可以做的第一件事

元字符是 []

[abc],[a-c],[0-9],[abc] \作為元字符在中括號內(nèi)失效,[^5] 匹配非'5'的字符,[5^] 將匹配 '5''^'

元字符是反斜杠,\

反斜杠來移除它們的特殊含義:\[\\,

'\' 開頭的特殊序列表示通常有用的預定義字符集

  • \d

    匹配任何十進制數(shù)字;這等價于類 [0-9]。

  • \D

    匹配任何非數(shù)字字符;這等價于類 [^0-9]。

  • \s

    匹配任何空白字符;這等價于類 [ \t\n\r\f\v]。轉(zhuǎn)義符在中括號中不失效嗎

  • \S

    匹配任何非空白字符;這相當于類 [^ \t\n\r\f\v]

  • \w

    匹配任何字母與數(shù)字字符;這相當于類 [a-zA-Z0-9_]。

  • \W

    匹配任何非字母與數(shù)字字符;這相當于類 [^a-zA-Z0-9_]。

元字符是 .

它匹配除換行符之外的任何內(nèi)容,并且有一個可選模式( re.DOTALL )甚至可以匹配換行符

重復:指定正則的某些部分必須重復一定次數(shù)

元字符是 *

一個逐步的例子將使這更加明顯。 讓我們考慮表達式 a[bcd]*b。 這個正則匹配字母 'a',類 [bcd] 中的零或多個字母,最后以 'b' 結(jié)尾。 現(xiàn)在想象一下這個正則與字符串 'abcbd' 匹配。

步驟 匹配 說明
1 a 正則中的 a 匹配。
2 abcbd 引擎盡可能多地匹配 [bcd]* ,直到字符串結(jié)束。
3 失敗 引擎嘗試匹配 b ,但是當前位置位于字符串結(jié)束,所以匹配失敗。
4 abcb 回退一次,[bcd]* 少匹配一個字符。
5 失敗 再次嘗試匹配 b , 但是當前位置是最后一個字符 'd' 。
6 abc 再次回退,所以 [bcd]* 只匹配 bc
6 abcb 再試一次 b 。 這次當前位置的字符是 'b' ,所以它成功了。

元字符是 +

ca+t 將匹配 'cat' (1 個 'a'),'caaat' (3 個 'a'),但不會匹配 'ct'

重復限定符。 問號字符 ? 匹配一次或零次

home-?brew 匹配 'homebrew''home-brew'

重復限定符是 {m,n}

a/{1,3}b 將匹配 'a/b' ,'a//b''a///b' 。 它不匹配沒有斜線的 'ab',或者有四個的 'a////b', {0,}* 相同, {1,} 相當于 + , {0,1}? 相同。 最好使用 *+? ,只要因為它們更短更容易閱讀。

使用正則表達式

re 模塊提供了正則表達式引擎的接口,允許你將正則編譯為對象,然后用它們進行匹配

編譯正則表達式

正則表達式被編譯成模式對象,模式對象具有各種操作的方法,例如搜索模式匹配或執(zhí)行字符串替換

p = re.compile('ab*')

re.compile() 也接受一個可選的 flags 參數(shù),用于啟用各種特殊功能和語法變體, p = re.compile('ab*', re.IGNORECASE)

正則作為字符串傳遞給 re.compile() ,將正則放在字符串中可以使 Python 語言更簡單,但有一個缺點:反斜杠災難。解決方案 r"\n" 是一個包含 '\''n' 的雙字符字符串,而 "\n" 是一個包含換行符的單字符字符串。

應用匹配

一旦你有一個表示編譯正則表達式的對象,你用它做什么? 模式對象有幾種方法和屬性。

方法 / 屬性 目的
match() 確定正則是否從字符串的開頭匹配。
search() 掃描字符串,查找此正則匹配的任何位置。
findall() 找到正則匹配的所有子字符串,并將它們作為列表返回。
finditer() 找到正則匹配的所有子字符串,并將它們返回為一個 iterator
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
>>> p.match("")
>>> print(p.match(""))
None
>>> m = p.match('tempo')
>>> m
<re.Match object; span=(0, 5), match='tempo'>

現(xiàn)在你可以檢查 匹配對象 以獲取有關(guān)匹配字符串的信息。 匹配對象實例也有幾個方法和屬性;最重要的是:

方法 / 屬性 目的
group() 返回正則匹配的字符串
start() 返回匹配的開始位置
end() 返回匹配的結(jié)束位置
span() 返回包含匹配 (start, end) 位置的元組

嘗試這些方法很快就會清楚它們的含義:

group() 返回正則匹配的子字符串。 start()end() 返回匹配的起始和結(jié)束索引。 span() 在單個元組中返回開始和結(jié)束索引。 由于 match() 方法只檢查正則是否在字符串的開頭匹配,所以 start() 將始終為零。 但是,模式的 search() 方法會掃描字符串,因此在這種情況下匹配可能不會從零開始。:

>>>

>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)
<re.Match object; span=(4, 11), match='message'>
>>> m.group()
'message'
>>> m.span()
(4, 11)

在實際程序中,最常見的樣式是在變量中存儲 匹配對象,然后檢查它是否為 None。 這通??雌饋硐?

p = re.compile( ... )
m = p.match( 'string goes here' )
if m:
    print('Match found: ', m.group())
else:
    print('No match')

兩種模式方法返回模式的所有匹配項。 findall() 返回匹配字符串的列表:

>>>

>>> p = re.compile(r'\d+')
>>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
['12', '11', '10']

在這個例子中需要 r 前綴,使字面為原始字符串字面,因為普通的“加工”字符串字面中的轉(zhuǎn)義序列不能被 Python 識別為正則表達式,導致 DeprecationWarning 并最終產(chǎn)生 SyntaxError。 請參閱 反斜杠災難

findall() 必須先創(chuàng)建整個列表才能返回結(jié)果。 finditer() 方法將一個 匹配對象 的序列返回為一個 iterator

>>>

>>> iterator = p.finditer('12 drummers drumming, 11 ... 10 ...')
>>> iterator  
<callable_iterator object at 0x...>
>>> for match in iterator:
...     print(match.span())
...
(0, 2)
(22, 24)
(29, 31)

模塊級別函

>>> print(re.match(r'From\s+', 'Fromage amk'))
None
>>> re.match(r'From\s+', 'From amk Thu May 14 19:12:10 1998')  
<re.Match object; span=(0, 5), match='From '>

編譯標志

這是一個可用標志表,以及每個標志的更詳細說明。

Flag 含義
ASCII, A 使幾個轉(zhuǎn)義如 \w、\b\s\d 匹配僅與具有相應特征屬性的 ASCII 字符匹配。
DOTALL, S 使 . 匹配任何字符,包括換行符。
IGNORECASE, I 進行大小寫不敏感匹配。
LOCALE, L 進行區(qū)域設置感知匹配。
MULTILINE, M 多行匹配,影響 ^$
VERBOSE, X (為 '擴展') 啟用詳細的正則,可以更清晰,更容易理解。

re.I | re.M 設置 IM 標志

這里的正則使用 re.VERBOSE;看看閱讀有多容易?: charref = re.compile(r""" &[#] # Start of a numeric entity reference ( 0[0-7]+ # Octal form | [0-9]+ # Decimal form | x[0-9a-fA-F]+ # Hexadecimal form ) ; # Trailing semicolon """, re.VERBOSE) 如果沒有詳細設置,正則將如下所示: charref = re.compile("&#(0[0-7]+" "|[0-9]+" "|x[0-9a-fA-F]+);")

更多元字符

Crow|Servo 將匹配 'Crow''Servo',而不是 'Cro'、'w''S''ervo'

print(re.search('^From', 'From Here to Eternity')) <re.Match object; span=(0, 4), match='From'> print(re.search('^From', 'Reciting From Memory')) None `

print(re.search('}$', '{block}')) <re.Match object; span=(6, 7), match='}'> >>> print(re.search('}$', '{block} ')) None >>> print(re.search('}$', '{block}\n')) <re.Match object; span=(6, 7), match='}'> `

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容