
微信公眾號:碼農充電站pro
個人主頁:https://codeshellme.github.io
0,什么是正則表達式
正則表達式(Regular Expression簡寫為Regex),又稱為規則表達式,它是一種強大的文本匹配模式,其用於在字符串中查找匹配符合特定規則的子串。
正則表達式是獨立於編程語言而存在的,它並不依賴於某種編程語言。只要一種編程語言實現了正則表達式引擎,那么這種編程語言,就具備了正則表達式模式匹配的功能。每種工具或編程語言對正則表達式的實現,雖有細節上的不同,但基本的使用是相同的。
正則表達式的基本工作原理如下:

1,正則表達式的由來
1956 年,美國數學家Stephen Kleene 在兩位神經生理學家(Warren McCulloch 和 Walter Pitts)的早期工作的基礎上,發表了一篇標題為神經網事件的表示法的論文,由此引入了正則表達式的概念。
之后,Unix 之父Ken Thompson把這一成果應用於計算搜索算法的一些早期研究。隨后,他將這一符號系統應用於Unix 系統中的 qed 編輯器,這是正則表達式的第一個實用程序。
此后,正則表達式被廣泛的應用於類Unix 系統的工具中,如 grep,perl 等。
2,正則表達式工具
RegexBuddy 是一個很不錯的軟件。
Regexr 是一個在線工具。
3,正則表達式語法
正則表達式由一些普通字符(比如英文字母,數字)和元字符(代表特定含義)組成。
正則表達式作為一個字符模板,在字符串中匹配一個或多個符合特定規則的子串。
3.1,元字符
元字符就是包含特定含義的字符。如果想匹配這些元字符,需要使用轉義字符\ 進行轉義。
下表是一些常用的元字符:
| 字符 | 含義 |
|---|---|
\ |
轉義字符,常用於轉義元字符 |
. |
匹配除換行符\n 之外的任何單字符 |
$ |
匹配字符串的結尾位置 |
^ |
匹配字符串的開始位置。當寫在中括號[]內時,表示不匹配該中括號中的字符集合 |
[^xy] |
匹配非x,非y字符 |
() |
被小括號包含的多個字符,將作為一整個字符 |
(pattern) |
寫在小括號()內的表達式,表示一個分組,用於提取內容 |
(?:pattern) |
只表示一個分組,不提取內容 |
[] |
被中括號包含的多個字符,這多個字符的關系是邏輯或的關系 |
[xyz] |
字符集合,匹配x或y或z |
[0-9] |
匹配0到9之間的數字 |
[a-z] |
匹配a到z之間的字符 |
[^a-z] |
匹配不在a到z范圍內的任意字符 |
| |
寫在兩個字符之間,代表邏輯或的關系 |
x|y |
匹配x 或 y |
\b |
匹配一個單詞邊界 |
\B |
匹配非單詞邊界 |
\d |
匹配一個數字字符,等價於[0-9] |
\D |
匹配一個非數字字符,等價於[^0-9] |
\s |
匹配任何空白字符,包括空格、制表符等 |
\S |
匹配任何非空白字符 |
\w |
匹配字母、數字、下划線,等價於[A-Za-z0-9_] |
\W |
匹配非字母、非數字、非下划線,等價於[^A-Za-z0-9_] |
\f |
匹配換頁符 |
\n |
匹配換行符 |
\r |
匹配回車符 |
\t |
匹配制表符 |
\v |
匹配垂直制表符 |
3.2,限定符
限定符也屬於元字符,用來限定一個子表達式出現的次數。
| 字符 | 含義 |
|---|---|
* |
匹配前面的子表達式零次或多次 |
+ |
匹配前面的子表達式一次或多次 |
? |
匹配前面的子表達式零次或一次 |
{n} |
匹配前面的子表達式n次 |
{n,} |
匹配前面的子表達式至少n次 |
{n,m} |
匹配前面的子表達式n 到m 次 |
4,正則表達式示例
我們逐個介紹一下每種元字符的使用方式,下面的例子我們都使用RegexBuddy 軟件來演示。
4.1,轉義字符\
轉義字符用來對一些元字符進行轉義,使這些元字符失去其特定的含義,只表示一個普通的字符。
比如我們想匹配字符串aaa^bbb 中的a^b 子串,我們需要用模式a\^b 來匹配,^ 之前需要加一個轉義字符\。

4.2,元字符.
元字符. 可匹配任意(除了換行符\n)的單字符,意思就是. 可以代表任意(除了換行符\n)的單字符。

4.3,開始位置^與結束位置$
符號^ 表示匹配的子串在行首,符號$ 表示匹配的子串在行尾。
匹配行首

匹配行尾

行首行尾

4.4,邏輯或|
符號| 寫在兩個子表達式之間表示邏輯或的意思。
例如模式串ab|cd,匹配ab 或 cd。

4.5,限定符
限定符用於限定一個子表達式出現的次數,一共6 種,這里給出一些示例。
符號*
模式串ab*c,表示字符a和c 之間需要出現0 次或多次字符b。

符號+
模式串ab+c,表示字符a和c 之間需要出現1 次或多次字符b,即至少出現1次字符b。

符號?
模式串ab?c,表示字符a和c 之間需要出現0 次或1次字符b。

符號{n}和{n,}和{n,m}
ab{3}c:符號b 出現的次數必須是3ab{3,}c:符號b 出現的次數必須大於等於3ab{3,5}c:符號b 出現的次數必須在3和5之間,包括3和5

4.6,字符簇[]
寫在中括號[] 內的多個字符代表邏輯或的意思。
模式串a[bef]c,表示a和c中間的字符必須是b或e或f。

當符號^ 寫在中括號[] 內時,表示邏輯非的意思。
模式串a[^bef]c,表示a和c中間的字符不能是b或e或f。

符號- 寫在中括號[],表示范圍的意思:
| 示例 | 含義 |
|---|---|
[a-z] |
表示a 到z 之間的任意字符 |
[A-Z] |
表示A 到Z 之間的任意字符 |
[0-9] |
表示0 到9 之間的任意數字,含義同\d |
[^0-9] |
表示任意非數字,含義同\D |
[A-Za-z0-9_] |
表示任意字母,數字或下划線 ,含義同\w |
[^A-Za-z0-9_] |
表示任意非字母,非數字,非下划線 ,含義同\W |
[ \f\r\t\n] |
表示任意的空白字符,含義同\s |
[^ \f\r\t\n] |
表示任意的非空白字符,含義同\S |
4.7,字符組合()
寫在小括號()中的多個字符,會被看成一個整體。

4.8,單詞邊界\b與\B
符號\b 是指一個單詞邊界,比如空白字符和標點符號等。
符號\B 表示非單詞邊界。

5,貪婪與非貪婪模式
正則表達式中貪婪的意思就是貪多,意思就是正則在匹配的過程中,總是去匹配盡可能多的字符,符號? 可以將貪婪轉換為非貪婪。

6,在Python 中使用正則
Python 中提供了re 模塊,用於支持正則表達式功能。
在python 中一般在表達式前加r,表示原始字符,不用考慮轉義的問題。例如r'abc'。
下面打開python 終端:
- 首先引入模塊,
import re help(re)可查看re 模塊幫助手冊dir(re)可查看其支持的屬性和方法
>>> python `打開python 終端`
_____________________________________________
Python 2.7.17 (default, Nov 7 2019, 10:07:09)
[GCC 7.4.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import re # 引入re 模塊
>>>
>>> help(re) # 查看幫助手冊
>>>
>>> dir(re) # 查看re 支持的屬性和方法
6.1,re 模塊常用方法
| 方法 | 含義 |
|---|---|
match |
用於匹配表達式 |
search |
查找匹配項 |
findall |
查找所有的匹配項 |
compile |
編譯正則表達式 |
詳細解釋:
match(pattern, string, flags=0)
Try to apply the pattern at the start of the string, returning
a match object, or None if no match was found.
search(pattern, string, flags=0)
Scan through string looking for a match to the pattern, returning
a match object, or None if no match was found.
findall(pattern, string, flags=0)
Return a list of all non-overlapping matches in the string.
If one or more groups are present in the pattern, return a
list of groups; this will be a list of tuples if the pattern
has more than one group.
Empty matches are included in the result.
compile(pattern, flags=0)
Compile a regular expression pattern, returning a pattern object.
可以看到,每個方法中都有一個flag 參數,它表示匹配模式,默認值為0,表示普通模式。
flag 參數的值有以下幾種選擇,可以使用符號| 連接多種選擇:
`I/IGNORECASE` Perform case-insensitive matching.
`L/LOCALE` Make \w, \W, \b, \B, dependent on the current locale.
`M/MULTILINE` "^" matches the beginning of lines (after a newline)
as well as the string.
"$" matches the end of lines (before a newline) as well
as the end of the string.
`S/DOTALL` "." matches any character at all, including the newline.
`X/VERBOSE` Ignore whitespace and comments for nicer looking RE's.
`U/UNICODE` Make \w, \W, \b, \B, dependent on the Unicode locale.
6.2,match 方法
re.match 嘗試從字符串的起始位置開始匹配:
- 成功:返回
SRE_Match對象 - 失敗:返回
None
>>> m = re.match(r'abc', 'abcde')
>>> print m # 匹配成功
<_sre.SRE_Match object at 0x7f91544cff80>
>>>
>>>
>>> m = re.match(r'abc', 'fabcde')
>>> print m # `fabcde` 不是以`abc` 開頭,匹配失敗
None
>>>
6.3,search 方法
re.search 掃描整個字符串,直到找到第一個成功的匹配:
- 成功:返回
SRE_Match對象 - 失敗:返回
None
>>> m = re.search(r'abc', 'abcde')
>>> print m # 匹配成功
<_sre.SRE_Match object at 0x7f91544cff80>
>>>
>>> m = re.search(r'abc', 'fabcde')
>>> print m # 匹配成功
<_sre.SRE_Match object at 0x7f9154521b90>
6.4,findall 方法
re.findall 在字符串中查找所有匹配的子串:
- 成功:返回一個列表
- 失敗:返回
空列表[]
>>> re.findall(r'abc', 'fabcdeabc')
['abc', 'abc'] # 找到兩個`abc` 子串
>>>
>>> re.findall(r'abce', 'fabcdeabc')
[] # 沒找到子串
>>>
6.5,compile 方法
在使用正則時,re 模塊會先將正則表達式進行編譯,然后才會去字符串中匹配。
如果一個正則表達式會使用很多次,我們可以使用re.compile 方法對表達式進行預編譯,這樣就不會在每次用到這個表達式時都進行編譯,有助於提高效率。
該方法返回一個SRE_Pattern 對象,該對象又包含match,search,findall 等方法,使用方法如下:
>>> reg = re.compile(r'abc') # 編譯
>>>
>>> type(reg)
<type '_sre.SRE_Pattern'>
>>>
>>> reg.findall('fabcdeabc') # 找到兩個
['abc', 'abc']
>>>
>>> reg.match('fabcdeabc') # 沒有匹配上
>>>
>>> reg.search('fabcdeabc') # 匹配上
<_sre.SRE_Match object at 0x7f9154521b90>
6.6,SRE_Match 對象
SRE_Match 對象用於獲取分組,寫在小括號()內的表達式是一個分組。
>>> # 正則中包含兩個分組
>>> m = re.match(r'(\d*)-(\w*)', '123-abc-')
>>> m
<_sre.SRE_Match object at 0x7f91544e0ae0>
>>> m.group(0) # 獲取整個匹配的串,同 m.group()
'123-abc'
>>> m.group(1) # 獲取第一個分組
'123'
>>> m.group(2) # 獲取第二個分組
'abc'
>>>
6.7,match,search,findall 比較
我們來看下match,search,findall 三個方法的異同點:
- match:必須從字符串的開頭匹配,只會有一個匹配項,返回結果是
SRE_Match對象 - search:掃描整個字符串,直到匹配到第一個為止,只會有一個匹配項,返回結果是
SRE_Match對象 - findall:掃描整個字符串,返回所有的匹配項,返回結果是一個字符串列表
(完。)
歡迎關注作者公眾號,獲取更過技術干貨。

