練習(xí) 31:正則表達(dá)式
譯者:飛龍
協(xié)議:CC BY-NC-SA 4.0
自豪地采用谷歌翻譯
正則表達(dá)式(RegEx)是一種簡(jiǎn)潔的方式椭豫,用于確定字符序列應(yīng)如何在字符串中匹配。通常大家都認(rèn)為它們是“可怕”的,但是子库,正如你所知道的温数,任何包含在恐懼中的東西通常都不是這樣百侧。正則表達(dá)式的事實(shí)是柬泽,它們是大約八個(gè)符號(hào)的集合蛇耀,告訴計(jì)算機(jī)如何匹配模式串。簡(jiǎn)單來說唇兑,他們很容易理解酒朵。人們遇到困難的地方是,嘗試使用難以置信的復(fù)雜的正則表達(dá)式扎附,其中解析器實(shí)際上會(huì)更好蔫耽。一旦你明白了這八個(gè)符號(hào)和正則表達(dá)式的限制,你就會(huì)看到它們根本不可怕留夜。
我打算讓你記憶更多東西匙铡,使你的的大腦為討論做好準(zhǔn)備。
^
錨定字符串開頭碍粥。只有字符串剛好位于開頭鳖眼,它才會(huì)匹配。
$
錨定字符串末尾嚼摩。只有字符串到達(dá)了末尾钦讳,它才會(huì)匹配。
.
任何單個(gè)字符枕面。接受任何單個(gè)字符的輸入蜂厅。
?
正則表達(dá)式的之前的部分是可選的,所以
A?
的意思是可選的字符A
膊畴。
*
之前的部分是零個(gè)或多個(gè)(任意個(gè))掘猿。選取正則表達(dá)式的之前的部分,重復(fù)接受或者跳過它唇跨。
A*
會(huì)接受"AAAAAAA"
或者"BQEFT"
稠通,因?yàn)樗锩嬗辛銈€(gè)A
。
+
之前的部分是一個(gè)或多個(gè)(至少一個(gè))买猖。和
*
類似改橘,但是只接受一個(gè)或多個(gè)這種字符。A+
會(huì)匹配"AAAAAAA"
玉控,但不是"BQEFT"
飞主。
[X-Y]
X
到Y
的字符范圍,接受任何范圍中列出的字符串高诺。[A-Z]
表示所有大寫英文字母碌识。許多常見字符范圍擁有\
快捷方式,你可以使用它來代替虱而。
()
捕獲這個(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è)來起步赋秀,重點(diǎn)是粗體的部分(錨定末尾利朵,之前部分可選)律想,以便你可以快速回憶它們并解釋他們的作用猎莲。
記住這些符號(hào)后,請(qǐng)查看以下正則表達(dá)式并將其翻譯成中文技即,并使用 Python re
庫(kù)來嘗試列出的字符串著洼,或你可以想到的任何其他字符串。
".*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 模塊來實(shí)現(xiàn)一個(gè)簡(jiǎn)單的正則表達(dá)式娇钱,至少執(zhí)行三個(gè)操作。這將是一個(gè)困難的挑戰(zhàn)绊困,但使用 Python re
庫(kù)來幫助你規(guī)劃和測(cè)試此正則表達(dá)式的實(shí)現(xiàn)文搂。然后,一旦你知道如何實(shí)現(xiàn)它秤朗,永遠(yuǎn)不要這樣做了煤蹭。人生苦短,不要做計(jì)算機(jī)已經(jīng)擅長(zhǎng)的事情取视。
研究性學(xué)習(xí)
- 擴(kuò)展你的記憶硝皂,來包括 Python
re
庫(kù)文檔中的所有可能的符號(hào)。 - 如果你想要匹配一個(gè)
*
字符作谭,那么你可以用\*
來轉(zhuǎn)義它吧彪。大多數(shù)其他符號(hào)也有類似的東西。 - 確保你知道如何使用
re.ASCII
丢早,因?yàn)槟承┙馕龅男枨笮枰?/li>
深入學(xué)習(xí)
看看regex
庫(kù)姨裸,如果你需要 Unicode 支持秧倾,那么這個(gè)更好。