溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何分析Python正則表達(dá)式re模塊

發(fā)布時(shí)間:2021-12-02 18:03:34 來(lái)源:億速云 閱讀:126 作者:柒染 欄目:編程語(yǔ)言

本篇文章為大家展示了如何分析Python正則表達(dá)式re模塊,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。

簡(jiǎn)介

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

要注意的是,正則表達(dá)式并不是一個(gè)程序,而是用于處理字符串的一種模式,如果你想用它來(lái)處理字符串,就必須使用支持正則表達(dá)式的工具,比如 Linux 中的 awk, sed, grep,或者編程語(yǔ)言 Perl, Python, Java 等等。

正則表達(dá)式有多種不同的風(fēng)格,下表列出了適用于 Python 或 Perl 等編程語(yǔ)言的部分元字符以及說(shuō)明:

如何分析Python正則表達(dá)式re模塊

re 模塊

在 Python 中,我們可以使用內(nèi)置的 re 模塊來(lái)使用正則表達(dá)式。

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

r'python\.org'

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

  • compile 函數(shù)

  • match 函數(shù)

  • search 函數(shù)

  • findall 函數(shù)

  • finditer 函數(shù)

  • split 函數(shù)

  • sub 函數(shù)

  • subn 函數(shù)

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

  • 使用 compile 函數(shù)將正則表達(dá)式的字符串形式編譯為一個(gè) Pattern 對(duì)象

  • 通過(guò) Pattern 對(duì)象提供的一系列方法對(duì)文本進(jìn)行匹配查找,獲得匹配結(jié)果(一個(gè) Match 對(duì)象)

  • ***使用 Match 對(duì)象提供的屬性和方法獲得信息,根據(jù)需要進(jìn)行其他的操作

compile 函數(shù)

compile 函數(shù)用于編譯正則表達(dá)式,生成一個(gè) Pattern 對(duì)象,它的一般使用形式如下:

re.compile(pattern[, flag])

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

下面,讓我們看看例子。

import re

# 將正則表達(dá)式編譯成 Pattern 對(duì)象
pattern = re.compile(r'\d+')

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

  • match 方法

  • search 方法

  • findall 方法

  • finditer 方法

  • split 方法

  • sub 方法

  • subn 方法

match 方法

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

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

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

當(dāng)匹配成功時(shí),返回一個(gè) Match 對(duì)象,如果沒有匹配上,則返回 None。

看看例子。

>>> import re
>>> pattern = re.compile(r'\d+')                    # 用于匹配至少一個(gè)數(shù)字
>>> 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                                         # 返回一個(gè) Match 對(duì)象
<_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)

在上面,當(dāng)匹配成功時(shí)返回一個(gè) Match 對(duì)象,其中:

  • group([group1, &hellip;]) 方法用于獲得一個(gè)或多個(gè)分組匹配的字符串,當(dāng)要獲得整個(gè)匹配的子串時(shí),可直接使用 group() 或 group(0)

  • start([group]) 方法用于獲取分組匹配的子串在整個(gè)字符串中的起始位置(子串***個(gè)字符的索引),參數(shù)默認(rèn)值為 0;

  • end([group]) 方法用于獲取分組匹配的子串在整個(gè)字符串中的結(jié)束位置(子串***一個(gè)字符的索引+1),參數(shù)默認(rèn)值為 0;

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

再看看一個(gè)例子:

>>> import re
>>> pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I)   # re.I 表示忽略大小寫
>>> m = pattern.match('Hello World Wide Web')
>>> print m                               # 匹配成功,返回一個(gè) Match 對(duì)象
<_sre.SRE_Match object at 0x10bea83e8>
>>> m.group(0)                            # 返回匹配成功的整個(gè)子串
'Hello World'
>>> m.span(0)                             # 返回匹配成功的整個(gè)子串的索引
(0, 11)
>>> m.group(1)                            # 返回***個(gè)分組匹配成功的子串
'Hello'
>>> m.span(1)                             # 返回***個(gè)分組匹配成功的子串的索引
(0, 5)
>>> m.group(2)                            # 返回第二個(gè)分組匹配成功的子串
'World'
>>> m.span(2)                             # 返回第二個(gè)分組匹配成功的子串
(6, 11)
>>> m.groups()                            # 等價(jià)于 (m.group(1), m.group(2), ...)
('Hello', 'World')
>>> m.group(3)                            # 不存在第三個(gè)分組
Traceback (most recent call last):
  File "<stdin>", line 1, in <module> IndexError: no such group

search 方法

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

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

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

當(dāng)匹配成功時(shí),返回一個(gè) Match 對(duì)象,如果沒有匹配上,則返回 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)  # 指定字符串區(qū)間
>>> m
<_sre.SRE_Match object at 0x10cc03b28>
>>> m.group()
'34'
>>> m.span()
(13, 15)

再來(lái)看一個(gè)例子:

# -*- coding: utf-8 -*-
import re

# 將正則表達(dá)式編譯成 Pattern 對(duì)象
pattern = re.compile(r'\d+')

# 使用 search() 查找匹配的子串,不存在匹配的子串時(shí)將返回 None
# 這里使用 match() 無(wú)法成功匹配
m = pattern.search('hello 123456 789')

if m:
    # 使用 Match 獲得分組信息
    print 'matching string:',m.group()
    print 'position:',m.span()

執(zhí)行結(jié)果:

matching string: 123456
position: (6, 12)

findall 方法

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

findall 方法的使用形式如下:

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

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

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

看看例子:

import re

pattern = re.compile(r'\d+')   # 查找數(shù)字
result1 = pattern.findall('hello 123456 789')
result2 = pattern.findall('one1two2three3four4', 0, 10)

print result1
print result2

執(zhí)行結(jié)果:

['123456', '789']
['1', '2']

finditer 方法

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

看看例子:

# -*- 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 對(duì)象
    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())

執(zhí)行結(jié)果:

<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 用于指定***分割次數(shù),不指定將全部分割。

看看例子:

import re

p = re.compile(r'[\s\,\;]+')
print p.split('a,b;; c   d')

執(zhí)行結(jié)果:

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

sub 方法

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

sub(repl, string[, count])

其中,repl 可以是字符串也可以是一個(gè)函數(shù):

  • 如果 repl 是字符串,則會(huì)使用 repl 去替換字符串每一個(gè)匹配的子串,并返回替換后的字符串,另外,repl 還可以使用 \id 的形式來(lái)引用分組,但不能使用編號(hào) 0;

  • 如果 repl 是函數(shù),這個(gè)方法應(yīng)當(dāng)只接受一個(gè)參數(shù)(Match 對(duì)象),并返回一個(gè)字符串用于替換(返回的字符串中不能再引用分組)。

count 用于指定最多替換次數(shù),不指定時(shí)全部替換。

看看例子:

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)         # 最多替換一次

執(zhí)行結(jié)果:

hello world, hello world
123 hello, 456 hello
hi 123, hi 456
hi 123, hello 456

subn 方法

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

subn(repl, string[, count])

它返回一個(gè)元組:

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

元組有兩個(gè)元素,***個(gè)元素是使用 sub 方法的結(jié)果,第二個(gè)元素返回原字符串被替換的次數(shù)。

看看例子:

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)

執(zhí)行結(jié)果:

('hello world, hello world', 2)
('123 hello, 456 hello', 2)
('hi 123, hi 456', 2)
('hi 123, hello 456', 1)

其他函數(shù)

事實(shí)上,使用 compile 函數(shù)生成的 Pattern 對(duì)象的一系列方法跟 re 模塊的多數(shù)函數(shù)是對(duì)應(yīng)的,但在使用上有細(xì)微差別。

match 函數(shù)

match 函數(shù)的使用形式如下:

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

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

而 Pattern 對(duì)象的 match 方法使用形式是:

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

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

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

執(zhí)行結(jié)果:

m1 is: None
matching string: 12

search 函數(shù)

search 函數(shù)的使用形式如下:

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

search 函數(shù)不能指定字符串的搜索區(qū)間,用法跟 Pattern 對(duì)象的 search 方法類似。

findall 函數(shù)

findall 函數(shù)的使用形式如下:

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

findall 函數(shù)不能指定字符串的搜索區(qū)間,用法跟 Pattern 對(duì)象的 findall 方法類似。

看看例子:

import re

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

# 輸出
['12345', '789']

finditer 函數(shù)

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

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

split 函數(shù)

split 函數(shù)的使用形式如下:

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

sub 函數(shù)

sub 函數(shù)的使用形式如下:

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

subn 函數(shù)

subn 函數(shù)的使用形式如下:

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

到底用哪種方式

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

  • 使用 re.compile 函數(shù)生成一個(gè) Pattern 對(duì)象,然后使用 Pattern 對(duì)象的一系列方法對(duì)文本進(jìn)行匹配查找;

  • 直接使用 re.match, re.search 和 re.findall 等函數(shù)直接對(duì)文本匹配查找;

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

先看第 1 種用法:

import re

# 將正則表達(dá)式先編譯成 Pattern 對(duì)象
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')

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

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

匹配中文

在某些情況下,我們想匹配文本中的漢字,有一點(diǎn)需要注意的是,中文的 unicode 編碼范圍 主要在 [\u4e00-\u9fa5],這里說(shuō)主要是因?yàn)檫@個(gè)范圍并不完整,比如沒有包括全角(中文)標(biāo)點(diǎn),不過(guò),在大部分情況下,應(yīng)該是夠用的。

假設(shè)現(xiàn)在想把字符串 title = u'你好,hello,世界' 中的中文提取出來(lái),可以這么做:

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

import re

title = u'你好,hello,世界'
pattern = re.compile(ur'[\u4e00-\u9fa5]+')
result = pattern.findall(title)

print result

注意到,我們?cè)谡齽t表達(dá)式前面加上了兩個(gè)前綴 ur,其中 r 表示使用原始字符串,u 表示是 unicode 字符串。

執(zhí)行結(jié)果:

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

貪婪匹配

在 Python 中,正則匹配默認(rèn)是貪婪匹配(在少數(shù)語(yǔ)言中可能是非貪婪),也就是匹配盡可能多的字符。

比如,我們想找出字符串中的所有 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

執(zhí)行結(jié)果:

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

由于正則匹配是貪婪匹配,也就是盡可能多的匹配,因此,在成功匹配到***個(gè) </div> 時(shí),它還會(huì)向右嘗試匹配,查看是否還有更長(zhǎng)的可以成功匹配的子串。

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

import re

content = 'aa<div>test1</div>bb<div>test2</div>cc'
pattern = re.compile(r'<div>.*?</div>')    # 加上 ?
result = pattern.findall(content)

print result

結(jié)果:

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

小結(jié)

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

  • 使用 compile 函數(shù)將正則表達(dá)式的字符串形式編譯為一個(gè) Pattern 對(duì)象;

  • 通過(guò) Pattern 對(duì)象提供的一系列方法對(duì)文本進(jìn)行匹配查找,獲得匹配結(jié)果(一個(gè) Match 對(duì)象);

  • 使用 Match 對(duì)象提供的屬性和方法獲得信息,根據(jù)需要進(jìn)行其他的操作;

Python 的正則匹配默認(rèn)是貪婪匹配。

上述內(nèi)容就是如何分析Python正則表達(dá)式re模塊,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI