Regex 正則表達式入門


在這里插入圖片描述

微信公眾號:碼農充電站pro
個人主頁:https://codeshellme.github.io


0,什么是正則表達式

正則表達式Regular Expression簡寫為Regex),又稱為規則表達式,它是一種強大的文本匹配模式,其用於在字符串中查找匹配符合特定規則的子串。

正則表達式是獨立於編程語言而存在的,它並不依賴於某種編程語言。只要一種編程語言實現了正則表達式引擎,那么這種編程語言,就具備了正則表達式模式匹配的功能。每種工具編程語言對正則表達式的實現,雖有細節上的不同,但基本的使用是相同的。

正則表達式的基本工作原理如下:

在這里插入圖片描述

1,正則表達式的由來

1956 年,美國數學家Stephen Kleene 在兩位神經生理學家(Warren McCullochWalter Pitts)的早期工作的基礎上,發表了一篇標題為神經網事件的表示法的論文,由此引入了正則表達式的概念。

之后,Unix 之父Ken Thompson把這一成果應用於計算搜索算法的一些早期研究。隨后,他將這一符號系統應用於Unix 系統中的 qed 編輯器,這是正則表達式的第一個實用程序。

此后,正則表達式被廣泛的應用於類Unix 系統的工具中,如 grepperl 等。

2,正則表達式工具

RegexBuddy 是一個很不錯的軟件。

Regexr 是一個在線工具。

3,正則表達式語法

正則表達式由一些普通字符(比如英文字母,數字)和元字符(代表特定含義)組成。

正則表達式作為一個字符模板,在字符串中匹配一個或多個符合特定規則的子串。

3.1,元字符

元字符就是包含特定含義的字符。如果想匹配這些元字符,需要使用轉義字符\ 進行轉義。

下表是一些常用的元字符:

字符 含義
\ 轉義字符,常用於轉義元字符
. 匹配除換行符\n 之外的任何單字符
$ 匹配字符串的結尾位置
^ 匹配字符串的開始位置。當寫在中括號[]內時,表示不匹配該中括號中的字符集合
[^xy] 匹配非x非y字符
() 被小括號包含的多個字符,將作為一整個字符
(pattern) 寫在小括號()內的表達式,表示一個分組,用於提取內容
(?:pattern) 只表示一個分組,不提取內容
[] 被中括號包含的多個字符,這多個字符的關系是邏輯或的關系
[xyz] 字符集合,匹配xyz
[0-9] 匹配09之間的數字
[a-z] 匹配az之間的字符
[^a-z] 匹配不在az范圍內的任意字符
| 寫在兩個字符之間,代表邏輯或的關系
x|y 匹配xy
\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,匹配abcd


在這里插入圖片描述


4.5,限定符

限定符用於限定一個子表達式出現的次數,一共6 種,這里給出一些示例。

符號*

模式串ab*c,表示字符ac 之間需要出現0 次多次字符b


在這里插入圖片描述


符號+

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


在這里插入圖片描述


符號?

模式串ab?c,表示字符ac 之間需要出現0 次1次字符b


在這里插入圖片描述


符號{n}{n,}{n,m}

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

在這里插入圖片描述


4.6,字符簇[]

寫在中括號[] 內的多個字符代表邏輯或的意思。

模式串a[bef]c,表示ac中間的字符必須是bef


在這里插入圖片描述


當符號^ 寫在中括號[] 內時,表示邏輯非的意思。

模式串a[^bef]c,表示ac中間的字符不能是bef


在這里插入圖片描述


符號- 寫在中括號[],表示范圍的意思:

示例 含義
[a-z] 表示az 之間的任意字符
[A-Z] 表示AZ 之間的任意字符
[0-9] 表示09 之間的任意數字,含義同\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 對象,該對象又包含matchsearchfindall 等方法,使用方法如下:

>>> 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 比較

我們來看下matchsearchfindall 三個方法的異同點:

  • match:必須從字符串的開頭匹配,只會有一個匹配項,返回結果是SRE_Match 對象
  • search:掃描整個字符串,直到匹配到第一個為止,只會有一個匹配項,返回結果是SRE_Match 對象
  • findall:掃描整個字符串,返回所有的匹配項,返回結果是一個字符串列表

(完。)


歡迎關注作者公眾號,獲取更過技術干貨。

碼農充電站pro


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM