Python 正則表達式

2021-03-02 Python開發者

(點擊上方藍字,快速關注我們)

來源:geekvi

連結:segmentfault.com/a/1190000007929344

如有好文章投稿,請點擊 → 這裡了解詳情

簡介

正則表達式(regular expression)是可以匹配文本片段的模式。最簡單的正則表達式就是普通字符串,可以匹配其自身。比如,正則表達式 『hello』 可以匹配字符串 『hello』。

要注意的是,正則表達式並不是一個程序,而是用於處理字符串的一種模式,如果你想用它來處理字符串,就必須使用支持正則表達式的工具,比如 Linux 中的 awk, sed, grep,或者程式語言 Perl, Python, Java 等等。

正則表達式有多種不同的風格,下表列出了適用於 Python 或 Perl 等程式語言的部分元字符以及說明:

re 模塊

在 Python 中,我們可以使用內置的 re 模塊來使用正則表達式。

有一點需要特別注意的是,正則表達式使用 對特殊字符進行轉義,比如,為了匹配字符串 'python.org',我們需要使用正則表達式 'python.org',而 Python 的字符串本身也用 轉義,所以上面的正則表達式在 Python 中應該寫成 'python\.org',這會很容易陷入 的困擾中,因此,我們建議使用 Python 的原始字符串,只需加一個 r 前綴,上面的正則表達式可以寫成:

r'python\.org'

re 模塊提供了不少有用的函數,用以匹配字符串,比如:

compile 函數

match 函數

search 函數

findall 函數

finditer 函數

split 函數

sub 函數

subn 函數

re 模塊的一般使用步驟如下:

使用 compile 函數將正則表達式的字符串形式編譯為一個 Pattern 對象

通過 Pattern 對象提供的一系列方法對文本進行匹配查找,獲得匹配結果(一個 Match 對象)

最後使用 Match 對象提供的屬性和方法獲得信息,根據需要進行其他的操作

compile 函數

compile 函數用於編譯正則表達式,生成一個 Pattern 對象,它的一般使用形式如下:

re.compile(pattern[, flag])

其中,pattern 是一個字符串形式的正則表達式,flag 是一個可選參數,表示匹配模式,比如忽略大小寫,多行模式等。

下面,讓我們看看例子。

import re

 

# 將正則表達式編譯成 Pattern 對象

pattern = re.compile(r'\d+')

在上面,我們已將一個正則表達式編譯成 Pattern 對象,接下來,我們就可以利用 pattern 的一系列方法對文本進行匹配查找了。Pattern 對象的一些常用方法主要有:

match 方法

search 方法

findall 方法

finditer 方法

split 方法

sub 方法

subn 方法

match 方法

match 方法用於查找字符串的頭部(也可以指定起始位置),它是一次匹配,只要找到了一個匹配的結果就返回,而不是查找所有匹配的結果。它的一般使用形式如下:

match(string[, pos[, endpos]])

其中,string 是待匹配的字符串,pos 和 endpos 是可選參數,指定字符串的起始和終點位置,默認值分別是 0 和 len (字符串長度)。因此,當你不指定 pos 和 endpos 時,match 方法默認匹配字符串的頭部。

當匹配成功時,返回一個 Match 對象,如果沒有匹配上,則返回 None。

看看例子。

>>> import re

>>> pattern = re.compile(r'\d+')                    # 用於匹配至少一個數字

>>> m = pattern.match('one12twothree34four')        # 查找頭部,沒有匹配

>>> print m

None

>>> m = pattern.match('one12twothree34four', 2, 10) # 從'e'的位置開始匹配,沒有匹配

>>> print m

None

>>> m = pattern.match('one12twothree34four', 3, 10) # 從'1'的位置開始匹配,正好匹配

>>> print m                                         # 返回一個 Match 對象

<_sre.SRE_Match object at 0x10a42aac0>

>>> m.group(0)   # 可省略 0

'12'

>>> m.start(0)   # 可省略 0

3

>>> m.end(0)     # 可省略 0

5

>>> m.span(0)    # 可省略 0

(3, 5)

在上面,當匹配成功時返回一個 Match 對象,其中:

group([group1, …]) 方法用於獲得一個或多個分組匹配的字符串,當要獲得整個匹配的子串時,可直接使用 group() 或 group(0);

start([group]) 方法用於獲取分組匹配的子串在整個字符串中的起始位置(子串第一個字符的索引),參數默認值為 0;

end([group]) 方法用於獲取分組匹配的子串在整個字符串中的結束位置(子串最後一個字符的索引+1),參數默認值為 0;

span([group]) 方法返回 (start(group), end(group))。

再看看一個例子:

>>> import re

>>> pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I)   # re.I 表示忽略大小寫

>>> m = pattern.match('Hello World Wide Web')

>>> print m                               # 匹配成功,返回一個 Match 對象

<_sre.SRE_Match object at 0x10bea83e8>

>>> m.group(0)                            # 返回匹配成功的整個子串

'Hello World'

>>> m.span(0)                             # 返回匹配成功的整個子串的索引

(0, 11)

>>> m.group(1)                            # 返回第一個分組匹配成功的子串

'Hello'

>>> m.span(1)                             # 返回第一個分組匹配成功的子串的索引

(0, 5)

>>> m.group(2)                            # 返回第二個分組匹配成功的子串

'World'

>>> m.span(2)                             # 返回第二個分組匹配成功的子串

(6, 11)

>>> m.groups()                            # 等價於 (m.group(1), m.group(2), ...)

('Hello', 'World')

>>> m.group(3)                            # 不存在第三個分組

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

IndexError: no such group

search 方法

search 方法用於查找字符串的任何位置,它也是一次匹配,只要找到了一個匹配的結果就返回,而不是查找所有匹配的結果,它的一般使用形式如下:

search(string[, pos[, endpos]])

其中,string 是待匹配的字符串,pos 和 endpos 是可選參數,指定字符串的起始和終點位置,默認值分別是 0 和 len (字符串長度)。

當匹配成功時,返回一個 Match 對象,如果沒有匹配上,則返回 None。

讓我們看看例子:

>>> import re

>>> pattern = re.compile('\d+')

>>> m = pattern.search('one12twothree34four')  # 這裡如果使用 match 方法則不匹配

>>> m

<_sre.SRE_Match object at 0x10cc03ac0>

>>> m.group()

'12'

>>> m = pattern.search('one12twothree34four', 10, 30)  # 指定字符串區間

>>> m

<_sre.SRE_Match object at 0x10cc03b28>

>>> m.group()

'34'

>>> m.span()

(13, 15)

再來看一個例子:

# -*- coding: utf-8 -*-

 

import re

# 將正則表達式編譯成 Pattern 對象

pattern = re.compile(r'\d+')

# 使用 search() 查找匹配的子串,不存在匹配的子串時將返回 None

# 這裡使用 match() 無法成功匹配

m = pattern.search('hello 123456 789')

if m:

    # 使用 Match 獲得分組信息

    print 'matching string:',m.group()

    print 'position:',m.span()

執行結果:

matching string: 123456

position: (6, 12)

findall 方法

上面的 match 和 search 方法都是一次匹配,只要找到了一個匹配的結果就返回。然而,在大多數時候,我們需要搜索整個字符串,獲得所有匹配的結果。

findall 方法的使用形式如下:

findall(string[, pos[, endpos]])

其中,string 是待匹配的字符串,pos 和 endpos 是可選參數,指定字符串的起始和終點位置,默認值分別是 0 和 len (字符串長度)。

findall 以列表形式返回全部能匹配的子串,如果沒有匹配,則返回一個空列表。

看看例子:

import re

pattern = re.compile(r'\d+')   # 查找數字

result1 = pattern.findall('hello 123456 789')

result2 = pattern.findall('one1two2three3four4', 0, 10)

print result1

print result2

執行結果:

['123456', '789']

['1', '2']

finditer 方法

finditer 方法的行為跟 findall 的行為類似,也是搜索整個字符串,獲得所有匹配的結果。但它返回一個順序訪問每一個匹配結果(Match 對象)的迭代器。

看看例子:

# -*- coding: utf-8 -*-

 

import re

pattern = re.compile(r'\d+')

 

result_iter1 = pattern.finditer('hello 123456 789')

result_iter2 = pattern.finditer('one1two2three3four4', 0, 10)

 

print type(result_iter1)

print type(result_iter2)

 

print 'result1...'

for m1 in result_iter1:   # m1 是 Match 對象

    print 'matching string: {}, position: {}'.format(m1.group(), m1.span())

 

print 'result2...'

for m2 in result_iter2:

    print 'matching string: {}, position: {}'.format(m2.group(), m2.span())

執行結果:

<type 'callable-iterator'>

<type 'callable-iterator'>

result1...

matching string: 123456, position: (6, 12)

matching string: 789, position: (13, 16)

result2...

matching string: 1, position: (3, 4)

matching string: 2, position: (7, 8)

split 方法

split 方法按照能夠匹配的子串將字符串分割後返回列表,它的使用形式如下:

split(string[, maxsplit])

其中,maxsplit 用於指定最大分割次數,不指定將全部分割。

看看例子:

import re

p = re.compile(r'[\s\,\;]+')

print p.split('a,b;; c   d')

執行結果:

['a', 'b', 'c', 'd']

sub 方法

sub 方法用於替換。它的使用形式如下:

sub(repl, string[, count])

其中,repl 可以是字符串也可以是一個函數:

如果 repl 是字符串,則會使用 repl 去替換字符串每一個匹配的子串,並返回替換後的字符串,另外,repl 還可以使用 id 的形式來引用分組,但不能使用編號 0;

如果 repl 是函數,這個方法應當只接受一個參數(Match 對象),並返回一個字符串用於替換(返回的字符串中不能再引用分組)。

count 用於指定最多替換次數,不指定時全部替換。

看看例子:

import re

p = re.compile(r'(\w+) (\w+)')

s = 'hello 123, hello 456'

 

def func(m):

    return 'hi' + ' ' + m.group(2)

 

print p.sub(r'hello world', s)  # 使用 'hello world' 替換 'hello 123' 和 'hello 456'

print p.sub(r'\2 \1', s)        # 引用分組

print p.sub(func, s)

print p.sub(func, s, 1)         # 最多替換一次

執行結果:

hello world, hello world

123 hello, 456 hello

hi 123, hi 456

hi 123, hello 456

subn 方法

subn 方法跟 sub 方法的行為類似,也用於替換。它的使用形式如下:

subn(repl, string[, count])

它返回一個元組:

(sub(repl, string[, count]), 替換次數)

元組有兩個元素,第一個元素是使用 sub 方法的結果,第二個元素返回原字符串被替換的次數。

看看例子:

import re

p = re.compile(r'(\w+) (\w+)')

s = 'hello 123, hello 456'

 

def func(m):

    return 'hi' + ' ' + m.group(2)

 

print p.subn(r'hello world', s)

print p.subn(r'\2 \1', s)

print p.subn(func, s)

print p.subn(func, s, 1)

執行結果:

('hello world, hello world', 2)

('123 hello, 456 hello', 2)

('hi 123, hi 456', 2)

('hi 123, hello 456', 1)

其他函數

事實上,使用 compile 函數生成的 Pattern 對象的一系列方法跟 re 模塊的多數函數是對應的,但在使用上有細微差別。

match 函數

match 函數的使用形式如下:

re.match(pattern, string[, flags]):

其中,pattern 是正則表達式的字符串形式,比如 d+, [a-z]+。

而 Pattern 對象的 match 方法使用形式是:

match(string[, pos[, endpos]])

可以看到,match 函數不能指定字符串的區間,它只能搜索頭部,看看例子:

import re

 

m1 = re.match(r'\d+', 'One12twothree34four')

if m1:

    print 'matching string:',m1.group()

else:

    print 'm1 is:',m1

    

m2 = re.match(r'\d+', '12twothree34four')

if m2:

    print 'matching string:', m2.group()

else:

    print 'm2 is:',m2

執行結果:

m1 is: None

matching string: 12

search 函數

search 函數的使用形式如下:

re.search(pattern, string[, flags])

search 函數不能指定字符串的搜索區間,用法跟 Pattern 對象的 search 方法類似。

findall 函數

findall 函數的使用形式如下:

re.findall(pattern, string[, flags])

findall 函數不能指定字符串的搜索區間,用法跟 Pattern 對象的 findall 方法類似。

看看例子:

import re

 

print re.findall(r'\d+', 'hello 12345 789')

 

# 輸出

['12345', '789']

finditer 函數

finditer 函數的使用方法跟 Pattern 的 finditer 方法類似,形式如下:

re.finditer(pattern, string[, flags])

split 函數

split 函數的使用形式如下:

re.split(pattern, string[, maxsplit])

sub 函數

sub 函數的使用形式如下:

re.sub(pattern, repl, string[, count])

subn 函數

subn 函數的使用形式如下:

re.subn(pattern, repl, string[, count])

到底用哪種方式

從上文可以看到,使用 re 模塊有兩種方式:

使用 re.compile 函數生成一個 Pattern 對象,然後使用 Pattern 對象的一系列方法對文本進行匹配查找;

直接使用 re.match, re.search 和 re.findall 等函數直接對文本匹配查找;

下面,我們用一個例子展示這兩種方法。

先看第 1 種用法:

import re

 

# 將正則表達式先編譯成 Pattern 對象

pattern = re.compile(r'\d+')

 

print pattern.match('123, 123')

print pattern.search('234, 234')

print pattern.findall('345, 345')

再看第 2 種用法:

import re

 

print re.match(r'\d+', '123, 123')

print re.search(r'\d+', '234, 234')

print re.findall(r'\d+', '345, 345')

如果一個正則表達式需要用到多次(比如上面的 d+),在多種場合經常需要被用到,出於效率的考慮,我們應該預先編譯該正則表達式,生成一個 Pattern 對象,再使用該對象的一系列方法對需要匹配的文件進行匹配;而如果直接使用 re.match, re.search 等函數,每次傳入一個正則表達式,它都會被編譯一次,效率就會大打折扣。

因此,我們推薦使用第 1 種用法。

匹配中文

在某些情況下,我們想匹配文本中的漢字,有一點需要注意的是,中文的 unicode 編碼範圍 主要在 [u4e00-u9fa5],這裡說主要是因為這個範圍並不完整,比如沒有包括全形(中文)標點,不過,在大部分情況下,應該是夠用的。

假設現在想把字符串 title = u'你好,hello,世界' 中的中文提取出來,可以這麼做:

# -*- coding: utf-8 -*-

 

import re

 

title = u'你好,hello,世界'

pattern = re.compile(ur'[\u4e00-\u9fa5]+')

result = pattern.findall(title)

 

print result

注意到,我們在正則表達式前面加上了兩個前綴 ur,其中 r 表示使用原始字符串,u 表示是 unicode 字符串。

執行結果:

[u'\u4f60\u597d', u'\u4e16\u754c']

貪婪匹配

在 Python 中,正則匹配默認是貪婪匹配(在少數語言中可能是非貪婪),也就是匹配儘可能多的字符

比如,我們想找出字符串中的所有 div 塊:

import re

 

content = 'aa<div>test1</div>bb<div>test2</div>cc'

pattern = re.compile(r'<div>.*</div>')

result = pattern.findall(content)

 

print result

執行結果:

['<div>test1</div>bb<div>test2</div>']

由於正則匹配是貪婪匹配,也就是儘可能多的匹配,因此,在成功匹配到第一個

時,它還會向右嘗試匹配,查看是否還有更長的可以成功匹配的子串。

如果我們想非貪婪匹配,可以加一個 ?,如下:

import re

 

content = 'aa<div>test1</div>bb<div>test2</div>cc'

pattern = re.compile(r'<div>.*?</div>')    # 加上 ?

result = pattern.findall(content)

 

print result

結果:

['<div>test1</div>', '<div>test2</div>']

小結

使用 compile 函數將正則表達式的字符串形式編譯為一個 Pattern 對象;

通過 Pattern 對象提供的一系列方法對文本進行匹配查找,獲得匹配結果(一個 Match 對象);

最後使用 Match 對象提供的屬性和方法獲得信息,根據需要進行其他的操作;

參考資料

正則表達式 – 維基百科

Python正則表達式指南

覺得本文對你有幫助?請分享給更多人

關注「Python開發者」

看更多技術乾貨

相關焦點

  • Python正則表達式總結
    正則表達式 的起源、發展、流派、語法、引擎、優化等相關知識,今天我們主要來學習一下 正則表達式在 Python語言 中的應用!可以在這裡查看Python所有的內置模塊:https://docs.python.org/3/py-modindex.html#cap-r因為re是內置模塊,所以不需要再下載,使用時直接引入即可:re模塊官方文檔:https://docs.python.org/zh-cn/3.8/library/re.htmlre模塊庫源碼:https://github.com/python/cpython/blob
  • 萬字長文詳解Python正則表達式及re模塊
    exp) 零寬度負回顧後發斷言,來斷言此位置的前面不能匹配表達式exp,Python中提供的re模塊使Python擁有全部正則表達式的功能!語法格式如下:re.match(pattern, string, flags=0)pattern是匹配的正則表達式,string是要匹配的字符串。flags是標誌位,用於控制正則表達式的匹配方式,如:是否區分大小寫,多行匹配等等。
  • python正則表達式
    微信公眾號:學點啥玩點啥小白友好型python正則表達式 1#第7章 模式匹配與正則表達式
  • 學習Python正則表達式
    Python中的正則表達式(re)就可以解決這個問題!正則表達式正則表達式是一個具有特殊字符的序列。它有助於檢查字符串中的每個字符,看它是否與某個模式匹配:哪些字符在什麼位置出現了多少次。result = re.findall(r』\d』, text)這將返回所有數字,但每個元素只有一個數字:['1', '0', '0', '1', '1', '1', '1', '2', '3', '4', '5', '6', '7']r-python原始字符串這裡,r表示python原始字符串。
  • 原創通俗易懂的Python的正則表達式,建議收藏
    正則表達式正則表達式是一個特殊的字符序列,由普通字符和元字符組成。元字符能幫助你方便的檢查一個字符串是否與某種模式匹配。正則表達式應用的場景也非常多。常見的比如:搜尋引擎的搜索、爬蟲結果的匹配、文本數據的提取等等都會用到,所以掌握甚至精通正則表達式是一個硬性技能,非常必要。
  • Python正則表達式:特殊符號和字符
    正表達式為高級的文本模式匹配,抽取,與/或文本形式的搜索和替換功能提供了基礎。簡而言之,正則表達式(簡稱regex)是由一些字符和特殊符號組成的字符串,它描述了模式的重複或者表達多個字符。python通過標準庫中的re模塊來支持正則表達式。
  • Python3爬蟲(4)--python正則表達式詳細版
    等等,在python中,這些都可以用正則表達式處理函數進行處理。re 模塊使 Python 語言擁有全部的正則表達式功能。函數語法:re.search(pattern, string, [flags])re.match只匹配字符串的開始,如果字符串開始不符合正則表達式,則匹配失敗,函數返回None;而re.search匹配整個字符串,直到找到一個匹配。所以實際應用往往使用re.search()函數。pattern:匹配的正則表達式(參考後面的正則表達式匹配模式附件)。
  • Python正則表達式,這一篇就夠了!
    大多數程式語言的正則表達式設計都師從Perl,所以語法基本相似,不同的是每種語言都有自己的函數去支持正則,今天我們就來學習 Python中關於 正則表達式的函數。re模塊主要定義了9個常量、12個函數、1個異常,每個常量和函數豬哥都會通過實際代碼案例講解,讓大家能更直觀的了解其作用!註:為避免出現代碼格式錯亂,豬哥儘量使用代碼截圖演示哦。
  • Python正則表達式入門到入魔
    正則表達式被作為用來描述其稱之為「正則集的代數」的一種表達式,因而採用了「正則表達式」這個術語。Unix使用正則之後,正則表達式不斷的發展壯大,然後大規模應用於各種領域,根據這些領域各自的條件需要,又發展出了許多版本的正則表達式,出現了許多的分支。我們把這些分支叫做「流派」。
  • 妙用正則表達式--Python中的re模塊
    Python中的re模塊可以方便地引入正則表達式。利用正則表達式,我們可以對文本內容進行精確快捷地匹配和提取。與Stata相比,正則表達式的元字符是通用的,不同的是函數。re庫中有若干個函數各司其職,在上一篇推文《Python標準庫re:正則表達式》中我們介紹了re庫中的三個常用函數,現在小編將從實用的角度再介紹幾個常用的函數。
  • 教你學習:Python-100-Days-12 正則表達式
    教你學習: Python-100-Days-12 正則表達式本項目是參考項目內容,進行個人理解,和原有項目有出入,如想了解詳情,請自行百度去搜索項目在編寫處理字符串的程序或網頁時,經常會有查找符合某些複雜規則的字符串的需要
  • python正則表達式使用方法說明
    曾光紅/文 (同步發布豆瓜網)一、導入re庫python使用正則表達式要導入re庫。import re在re庫中。正則表達式通常被用來檢索查找、替換那些符合某個模式(規則)的文本。二、使用正則表達式步驟1、尋找規律;2、使用正則符號表示規律;3、提取信息,如果每一個字符都能匹配,則匹配成功;一旦有匹配不成功的字符則匹配失敗。
  • 【Python】一文讀懂Python正則表達式常用用法
    最簡單的正則表達式就是普通字符串,可以匹配其自身。比如,正則表達式 『hello』 可以匹配字符串 『hello』。要注意的是,正則表達式並不是一個程序,而是用於處理字符串的一種模式,如果你想用它來處理字符串,就必須使用支持正則表達式的工具,比如 Linux 中的 awk, sed, grep,或者程式語言 Perl, Python, Java 等等。
  • Python中正則表達式模塊詳解
    用來處理字符串,對字符串進行檢索和替換,另外正則在python爬蟲的應用也是相當廣泛!
  • Python之re模塊方法詳解(正則表達式)
    學習re模塊首先要對python正則表達式要了解,正則表達式是一個特殊的字符序列,它能幫助你方便的檢查一個字符串是否與某種模式匹配
  • Python:正則表達式基本符號總結
    字符串是我們在編程的時候很常用的一種數據類型,檢查會在字符串裡面查找一些內容,對於比較簡單的查找,字符串裡面就有一些內置的方法可以處理,對於比較複雜的字符串查找,或者是有一些內容經常變化的字符串裡面查找,那麼字符串內置的查找方法已經不好使了,滿足不了我們的要求,這個時候就得用正則表達式了,正則表達式就是用來匹配一些比較複雜的字符串。
  • Python正則表達式
    什麼是正則表達式?正則表達式(Regular Expression)通常被用來檢索、替換那些符合某個模式(規則)的文本。此處的Regular即是規則、規律的意思,Regular Expression即「描述某種規則的表達式」之意。
  • 推薦|Python 正則表達式 re 模塊簡明筆記
    最簡單的正則表達式就是普通字符串,可以匹配其自身。比如,正則表達式 『hello』 可以匹配字符串 『hello』。有一點需要特別注意的是,正則表達式使用 \ 對特殊字符進行轉義,比如,為了匹配字符串 『python.org』,我們需要使用正則表達式 'python\.org',而 Python 的字符串本身也用 \ 轉義,所以上面的正則表達式在 Python 中應該寫成 'python\\.org',這會很容易陷入 \ 的困擾中,因此,我們建議使用 Python 的原始字符串,只需加一個 r 前綴
  • python面試題匯總第06期-正則表達式(內附7題及答案)
    1.python正則表達式中匹配(match)和查找(search)的區別答:正則表達式中match和search的方法比較相似相同點:都是在一個字符串s中尋找pat子字符串,如果能找到,就返回一個Match對象,如果找不到,就返回None。不同點:mtach方法是從頭開始匹配,而search方法,可以在s字符串的任一位置查找。
  • Python中的正則表達式
    什麼是正則表達式正則表達式是用於處理字符串的強大工具,它使用預定義的特定模式去匹配一類具有共同特徵的字符串,主要用於快速、準確地完成複雜字符串的查找、替換等。正則表達式進行匹配的流程如下圖所示:正則表達式匹配過程是:依次拿出表達式和文本中的字符比較,如果每一個字符都能匹配,則匹配成功;一旦有匹配不成功的字符則匹配失敗。