笨辦法學(xué) Python · 續(xù) 練習(xí) 31:正則表達(dá)式

練習(xí) 31:正則表達(dá)式

原文:Exercise 31: Regular Expressions

譯者:飛龍

協(xié)議:CC BY-NC-SA 4.0

自豪地采用谷歌翻譯

正則表達(dá)式(RegEx)是一種簡(jiǎn)潔的方式,用于確定字符序列應(yīng)如何在字符串中匹配。通常大家都認(rèn)為它們是“可怕”的,但是,正如你所知道的,任何包含在恐懼中的東西通常都不是這樣。正則表達(dá)式的事實(shí)是,它們是大約八個(gè)符號(hào)的集合,告訴計(jì)算機(jī)如何匹配模式串。簡(jiǎn)單來(lái)說(shuō),他們很容易理解。人們遇到困難的地方是,嘗試使用難以置信的復(fù)雜的正則表達(dá)式,其中解析器實(shí)際上會(huì)更好。一旦你明白了這八個(gè)符號(hào)和正則表達(dá)式的限制,你就會(huì)看到它們根本不可怕。

我打算讓你記憶更多東西,使你的的大腦為討論做好準(zhǔn)備。

^

錨定字符串開(kāi)頭。只有字符串剛好位于開(kāi)頭,它才會(huì)匹配。

$

錨定字符串末尾。只有字符串到達(dá)了末尾,它才會(huì)匹配。

.

任何單個(gè)字符。接受任何單個(gè)字符的輸入。

?

正則表達(dá)式的之前的部分是可選的,所以A?的意思是可選的字符A

*

之前的部分是零個(gè)或多個(gè)(任意個(gè))。選取正則表達(dá)式的之前的部分,重復(fù)接受或者跳過(guò)它。A*會(huì)接受"AAAAAAA"或者"BQEFT",因?yàn)樗锩嬗辛銈€(gè)A

+

之前的部分是一個(gè)或多個(gè)(至少一個(gè))。和*類似,但是只接受一個(gè)或多個(gè)這種字符。A+會(huì)匹配"AAAAAAA",但不是"BQEFT"

[X-Y]

XY字符范圍,接受任何范圍中列出的字符串。[A-Z]表示所有大寫英文字母。許多常見(jiàn)字符范圍擁有\快捷方式,你可以使用它來(lái)代替。

()

捕獲這個(gè)正則表達(dá)式的部分,便于稍后使用。許多正則表達(dá)式庫(kù)將其用于替換、提取或修改文本。捕獲會(huì)選取正則表達(dá)式的()中的部分,并保存它便于以后使用。之后許多庫(kù)可以讓你引用這些捕獲。如果你使用([A-Z]+),它會(huì)捕獲一個(gè)或多個(gè)大寫英文單詞。

Python 的re庫(kù)列出了一些更多的符號(hào),但大多都是這八個(gè)的一些修飾符,或者不在正則表達(dá)式庫(kù)中經(jīng)常發(fā)現(xiàn)的額外功能。你將快速記住這八個(gè)來(lái)起步,重點(diǎn)是粗體的部分(錨定末尾,之前部分可選),以便你可以快速回憶它們并解釋他們的作用。

記住這些符號(hào)后,請(qǐng)查看以下正則表達(dá)式并將其翻譯成中文,并使用 Python re庫(kù)來(lái)嘗試列出的字符串,或你可以想到的任何其他字符串。

".*BC?$"

helloBC, helloB, helloA, helloBCX

"[A-Za-z][0-9]+"

A1232344, abc1234, 12345, b493034

"^[0-9]?a*b?.$"

0aaaax, aaab9, 9x, 88aabb, 9zzzz

"A+B+C+[xyz]*"

AAAABBCCCCCCxyxyz, ABBBBCCCxxxx, ABABABxxxx

一旦你翻譯了它們,使用Python re模塊,嘗試在 Shell 中嘗試它們,如下:

>>> import re
>>> m = re.match(r".*BC?$", "helloB").span()
>>> re.match(r".*BC?$", "helloB").span()
(0, 6)
>>> re.match(r"[A-Za-z][0-9]+", "A1232344").span()
(0, 8)
>>> re.match(r"[A-Za-z][0-9]+", "abc1234").span()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'span'
>>> re.match(r"[A-Za-z][0-9]+", "1234").span()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'span'
>>> re.match(r"[A-Za-z][0-9]+", "b493034").span()
(0, 7)
>>>

對(duì)于任何不匹配,你會(huì)得到AttributeError: 'NoneType',因?yàn)楫?dāng)你的正則表達(dá)式不匹配時(shí),re.match函數(shù)返回None

挑戰(zhàn)練習(xí)

挑戰(zhàn)是嘗試使用你的 FSM 模塊來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的正則表達(dá)式,至少執(zhí)行三個(gè)操作。這將是一個(gè)困難的挑戰(zhàn),但使用 Python re庫(kù)來(lái)幫助你規(guī)劃和測(cè)試此正則表達(dá)式的實(shí)現(xiàn)。然后,一旦你知道如何實(shí)現(xiàn)它,永遠(yuǎn)不要這樣做了。人生苦短,不要做計(jì)算機(jī)已經(jīng)擅長(zhǎng)的事情。

研究性學(xué)習(xí)

  • 擴(kuò)展你的記憶,來(lái)包括 Python re庫(kù)文檔中的所有可能的符號(hào)。
  • 如果你想要匹配一個(gè)*字符,那么你可以用\*來(lái)轉(zhuǎn)義它。大多數(shù)其他符號(hào)也有類似的東西。
  • 確保你知道如何使用re.ASCII,因?yàn)槟承┙馕龅男枨笮枰?/li>

深入學(xué)習(xí)

看看regex庫(kù),如果你需要 Unicode 支持,那么這個(gè)更好。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容