「正則表達式」的奇幻漂流之旅
什么是正則表達式呢?
想象一下這樣的場景:
1
你應該經(jīng)常使用 「CTRL + F」在文本文件中搜索關鍵詞,定位到自己想要看的地方。不過,有時候你可能并不一定記得你要搜索的具體內(nèi)容。比如你只知道關鍵詞的開頭是「馬」,結(jié)尾是「梅」,但就是不知道是「馬什么梅」,如何快速搜索替換?
2
你在爬取頁面的時候,得到的一堆 HTML 標簽,但是你只是想拿到其中的關鍵文本信息,怎么快速剔除掉 HTML 標簽,把自己想要的文本從里面提取出來呢?
3
如果你開發(fā)了一個網(wǎng)站,允許用戶注冊,但你要求用戶注冊的密碼需要含有大小寫字母和數(shù)字,怎么驗證呢?又,如何屏蔽用戶的違規(guī)言論呢?
4
你在使用命令行的時候,如何一步到位的管理相關的文件呢?比如 rm -rf * (咋這個目錄下的文件都被刪除了?)
...
你看,在這些場景中,我們都需要一個「東西」來「占位」,表達關鍵的信息,比如在場景 1 中,我們不知道具體叫 「馬什么梅」,但是知道它中間一定是個字,那么我們可以制定一個規(guī)則,說:「以后這玩意【??】就代表一個任意的中文字」。
?? = 任意一個中文字
如果你的編輯器遵循了這一規(guī)則,知道【??】就代表一個任意的中文字,那么我們接下來就可以根據(jù)這個規(guī)則,使用「馬??梅」進行快速匹配了。
所以其實,這個「東西」就是用來描述我們想要的規(guī)則的,對吧?
當然,你也知道,我們自己制定的「東西」,編輯器是不會聽我們的,如果我們能夠知道那些已經(jīng)被大多數(shù)遵循了的「東西」,不就可以做到快速匹配我們想要的內(nèi)容了嗎?
這些被遵循的「東西」,就是正則表達式的元字符。
找到那些被遵循的「東西」
先認識「.」 和 「*」
這兩玩意也許是我們最常用到的「東西」了,其中每個「.」用來表達的是「除了換行符以外的任何字符」,像這樣:

標高亮的表示被匹配到的字符
一個「.」只能表達一個字符,那如果很多豈不是得點點點點點到天荒地老?所以其實我們不必要這樣去用那么多點來匹配,我們可以在「.」后面使用 「*」,這樣編輯器就知道:「哦,你要找的是0個或者多個『.』」:

所以,「.」是用來描述相關字符,而「*」用來描述匹配次數(shù)的。
和「.」一樣
雖然這兩玩意已經(jīng)可以代表大多數(shù)內(nèi)容了,但是對于一些具體的內(nèi)容,比如數(shù)字,換行等,也有已經(jīng)被遵循的「東西」,和「.」一樣,常用到的有:

把這個看熟,你基本可以匹配大部分你需要的內(nèi)容了,比如你要在這里只找到「handsome」這個詞就可以這樣:

匹配多個字母,數(shù)字,下劃線:

只匹配字母:

反向匹配:

匹配回車:

你去玩幾下就都熟悉了。
和 「*」 一樣
我們知道 「*」代表的是匹配0次或多次。和 「*」 一樣也有表示次數(shù)的,比如具體多少次,0次或一次:

轉(zhuǎn)義
現(xiàn)在,你已經(jīng)知道了常用的「東西」,它們都代表著一定的規(guī)則,但如果有時候文本出現(xiàn)了和「東西」一樣的字符,怎么去匹配呢?
比如說,我們知道「.」是匹配除了換行外的所有字符,但如果文本就出現(xiàn)了「.」,我們只要匹配這個「.」,咋整?

我們可以使用轉(zhuǎn)義字符,也就是在 「.」前面加一個 「\」,就說明我們是真的要找的是「.」:

當你在 「東西」前面加一個「\」,它就失去了功效,變回了原來的模樣。
還會常用到這玩意「|」
這個你應該很熟悉,就是「或」的意思,在 「|」的兩邊,滿足其一即可。
a|b 匹配 a 或者 b。
比如判斷文件是不是圖片類型,就可以這樣:
^.*?.(gif|png|jpg)$
小試牛刀
現(xiàn)在,找到了這些「東西」,也知道了轉(zhuǎn)義....現(xiàn)在我們來寫一個正則表達式,匹配郵箱的規(guī)則吧。
我們知道,郵箱的格式是這樣的:
我們可以發(fā)現(xiàn),郵箱有兩很明顯的特征點:「@」和「.」,而在「@」和 「.」前面和后面可以是一個或多個「大小寫字母或數(shù)字或下劃線」。
我們可以從開始到結(jié)束的特征點寫出來:
^[大小寫字母或數(shù)字或下劃線]+@[大小寫字母或數(shù)字或下劃線]+\.[大小寫字母或數(shù)字或下劃線]+$
替換成我們知道的「東西」:
^[a-zA-Z0-9_]+@[a-zA-Z0-9_]+\.[a-zA-Z0-9_]+$
好用的 ()
在這些「東西」里,()能夠進行分組,這對于我們在提取匹配我們關心的內(nèi)容很有幫助,比如我們要提取這樣的內(nèi)容:

我們可以使用 ()對相關的匹配進行分組,這樣得到多個分組(group1、group2、group3...)結(jié)果,這樣可以很方便的從中提取內(nèi)容,像這樣:

.*? 和 .*
這兩玩意都是匹配多個字符的「東西」,不過一個帶了「?」一個不帶,它們有什么區(qū)別呢?
.*? 表示的是非貪婪匹配
.* 表示的是貪婪匹配
啥意思呢?
舉一個最簡單的例子,比如我們有一個這樣的文本:
abcdefghijkabcdefghijkabcdefghijkabcdefghijk
如果我們想從中提取 a 到 k 的內(nèi)容,你可以發(fā)現(xiàn),當我們「貪婪」的時候得到的結(jié)果就是這樣的:
abcdefghijkabcdefghijkabcdefghijkabcdefghijk
「非貪婪」的時候,得到的結(jié)果就是這樣的:
abcdefghijk
那么用在它們兩身上,就是這樣的,貪婪:

非貪婪:

意思就是這么個意思~
ok,這就是我常常會使用到的正則表達式,在 Python 中,有個 re 庫可以專門操作這些玩意的,你可以到下面這個鏈接看到具體的解釋:
https://docs.python.org/zh-cn/3/library/re.html
順便,再給你推薦幾個正則表達式可以參考的地方:
這里,有圖文相關的正則表達式給你參考:
https://github.com/cdoco/common-regex

這里,可以讓你校驗自己寫的正則:
https://regexr.com/

這里,有多個語言版本的正則表達式教程(如果你想更進一步了解反向引用,零寬斷言的可以看看):
https://github.com/ziishaned/learn-regex/blob/master/README.md

我在上面演示用到的插件,叫「Regex Matcher」。
ok,以上就是小編今天給你帶來的分享,正則表達式算是基礎且通用的技能了,希望對你有幫助,如果有的話,請拼命點贊分享贊賞一波,哈哈,那么我們下回見,peace!
推薦閱讀:
入門: 最全的零基礎學Python的問題 | 零基礎學了8個月的Python | 實戰(zhàn)項目 |學Python就是這條捷徑
干貨:爬取豆瓣短評,電影《后來的我們》 | 38年NBA最佳球員分析 | 從萬眾期待到口碑撲街!唐探3令人失望 | 笑看新倚天屠龍記 | 燈謎答題王 |用Python做個海量小姐姐素描圖 |
趣味:彈球游戲 | 九宮格 | 漂亮的花 | 兩百行Python《天天酷跑》游戲!
AI: 會做詩的機器人 | 給圖片上色 | 預測收入 | 碟中諜這么火,我用機器學習做個迷你推薦系統(tǒng)電影
年度爆款文案
點這里,直達菜鳥學PythonB站??!

