正則表達式(三):python re模塊

以下示例所使用 python 版本為: 3.7

python 提供 re 模塊,來滿足正則表達式的使用。在開始介紹 re 模塊之前,首先說明一下兩個小內(nèi)容:

  1. 轉(zhuǎn)義字符 \

轉(zhuǎn)義字符作用是使得字符失去原本的意思,去表示另外一個作用。例如字符 d 表示一個普通的字符 d, 加 \ 轉(zhuǎn)義后 \d 表示數(shù)字,字符 s 經(jīng)轉(zhuǎn)義后,\s 表示空白字符。

如果要匹配轉(zhuǎn)義符號 \ 本身,則需要表達為 \\ 。而在編程語言中要表達兩個轉(zhuǎn)義符號 \\,則需要對每個轉(zhuǎn)義符號進行轉(zhuǎn)義,即形式為 \\\\,需要四個轉(zhuǎn)義符號才能完成用于匹配一個轉(zhuǎn)義符號 \ 的正則表達式。

為了減弱轉(zhuǎn)義字符使用上的麻煩,能夠?qū)⑹褂谜叩淖⒁饬性谡齽t表達式的編寫上,這里推薦所有的正則表達式開頭使用 r 字符開頭,表示正則內(nèi)容作為原始字符串輸入到 re 模塊的使用中。即編程環(huán)境中 r'\\' 直接作為正則表達式使用,來完成對字符 \ 的匹配。

示例:

import re

reg = r'\\'
str = '\\'    #轉(zhuǎn)義符號,str實際值為\

if re.match(reg,str):
    print('match {}'.format(str))
------------------------
運行結(jié)果:
match \
  1. Pattern、Match對象

在re模塊中使用正則表達式完成字符串處理有兩種方式:

  • 在 python 中可以直接使用 re 模塊生成 Match 對象,完成字符串處理。
    示例:
import re

reg = r'abc'
str = 'abc'

mattern = re.match(reg,str)
print(mattern .group())
------------------------
運行結(jié)果:
abc
  • 使用 re 模塊生成 Pattern 對象,然后使用 Pattern 對象生成 Match 對象,完成字符串處理。
    示例:
import re

reg = r'abc'
str = 'abc'

pattern = re.compile(reg)
match = pattern.match(str)
print(match.group())
------------------------
運行結(jié)果:
abc

這兩種方式執(zhí)行效果基本一樣,觀察 re 模塊源代碼:

模塊: \Python37\Lib\re.py

# --------------------------------------------------------------------
# public interface

def 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."""
    return _compile(pattern, flags).match(string)

def compile(pattern, flags=0):                #第二種方式
    "Compile a regular expression pattern, returning a Pattern object."
    return _compile(pattern, flags)

# --------------------------------------------------------------------
# internals

_cache = {}  # ordered!

_MAXCACHE = 512
def _compile(pattern, flags):
    # internal: compile pattern
    if isinstance(flags, RegexFlag):
        flags = flags.value
    try:
        return _cache[type(pattern), pattern, flags]         #從緩存字典中查詢
    except KeyError:
        pass
    if isinstance(pattern, Pattern):
        if flags:
            raise ValueError(
                "cannot process flags argument with a compiled pattern")
        return pattern
    if not sre_compile.isstring(pattern):
        raise TypeError("first argument must be string or compiled pattern")
    p = sre_compile.compile(pattern, flags)
    if not (flags & DEBUG):
        if len(_cache) >= _MAXCACHE:
            # Drop the oldest item
            try:
                del _cache[next(iter(_cache))]
            except (StopIteration, RuntimeError, KeyError):
                pass
        _cache[type(pattern), pattern, flags] = p         #添加到緩存字典中
    return p

觀察源碼可知, re 模塊提供的 compile 函數(shù)和 match 函數(shù),都需要先通過 _compile(pattern, flags) 函數(shù)生成一個 Pattern 對象,區(qū)別在于 match 函數(shù)直接在生成 Pattern 對象后調(diào)用了 match 函數(shù)。
觀察 _compile(pattern, flags) 函數(shù)體可知,首先會從緩存字典中查詢是否已經(jīng)存在 Pattern 對象,存在則返回,不存在則生成該 Pattern 對象,添加到緩存字典后返回。

由此可知,直接使用 re 模塊的 match 函數(shù)來生成 Match 對象,和使用 re 模塊的 compile 函數(shù)生成 Pattern 對象,然后再利用 match 函數(shù)生成 Match 對象完成字符串處理,這兩種方式都是首先調(diào)用 _compile(pattern, flags) 函數(shù)生成一個Pattern對象,然后再使用該 Pattern 對象的 match 函數(shù)生成 Match 對象。

所以兩種方式基本相同,區(qū)別只在于當(dāng) Pattern 對象多次使用時,第一種方式會存在多次查詢緩存操作,且緩存字典容量是有限制的,超出后會刪除最先添加的 Pattern 對象,所以推薦所有的正則中都使用構(gòu)造的 Pattern 對象來完成字符串處理。

下面列出 Pattern 對象中使用到的函數(shù):
函數(shù)名 作用
match(string, pos=0, endpos=-1) 在指定范圍內(nèi),從指定的起始位置開始匹配,得到匹配對象則返回
search(string, pos=0, endpos=-1) 在指定范圍內(nèi),從任意位置開始匹配,得到匹配對象則返回
findall(string, pos=0, endpos=-1) 在指定范圍內(nèi),返回所有匹配結(jié)果構(gòu)成的列表
finditer(string, pos=0, endpos=-1) 在指定范圍內(nèi),返回所有匹配對象構(gòu)成的迭代器
split(string, maxsplit=0) 按照指定的分割次數(shù),返回分割得到的結(jié)果列表
sub(repl, string, count=0) 按照指定的替換規(guī)則和替換次數(shù),返回替換后的結(jié)果
subn(repl, string, count=0) 按照指定的替換規(guī)則和替換次數(shù),返回替換后的結(jié)果和替換次數(shù)構(gòu)成的元組
  • match 函數(shù)

match 函數(shù)返回指定范圍內(nèi),從指定起始位置開始匹配到的對象。使用過程中只有三點需要注意一下:
1. 可以指定匹配的范圍,默認范圍是 0 到 len(str)
2. 匹配是從指定的起始位置開始的,也就是固定了開始位置
3. 匹配成功則返回,也就是只返回一個匹配對象

示例:

import re

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

str1 = 'a1b2c3'

match1 = pattern.match(str1)
match2 = pattern.match(str1,1)

print('match1 = {}'.format(match1))
if match1:
    print('match1 matched = {}'.format(match1.group()))

print('match2 = {}'.format(match2))
if match2:
    print('match2 matched = {}'.format(match2.group()))
運行結(jié)果:
match1 = None
match2 = <re.Match object; span=(1, 2), match='1'>
match2 matched = 1
  • search 函數(shù)

search 函數(shù)返回指定范圍內(nèi),從任意起始位置開始匹配到的對象。使用過程中只有三點需要注意一下:
1. 可以指定匹配的范圍,默認范圍是 0 到 len(str)
2. 匹配是從范圍內(nèi)的任意起始位置開始的,也就是不固定開始位置
3. 匹配成功則返回,也就是只返回一個匹配對象

示例:

import re

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

str1 = 'a1b2c3'

match1 = pattern.search(str1)

print('match1 = {}'.format(match1))
if match1:
    print('match1 matched = {}'.format(match1.group()))
運行結(jié)果:
match1 = <re.Match object; span=(1, 2), match='1'>
match1 matched = 1

比較 match 和 search 函數(shù)的使用:兩個函數(shù)都是一次匹配,得到結(jié)果則返回 (None 或 Match 對象),區(qū)別在于 match 函數(shù)從指定的起始位置開始匹配,search 函數(shù)從指定范圍內(nèi)的任意位置開始。

  • findall 函數(shù)

findall 函數(shù)返回指定范圍內(nèi),所有匹配結(jié)果構(gòu)成的列表。使用過程中只有兩點需要注意一下:
1. 可以指定匹配的范圍,默認范圍是 0 到 len(str)
2. 返回的是一個列表,元素是 str 對象,而非 Match 對象

示例:

import re

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

str1 = 'a1b2c3'

match1 = pattern.findall(str1)

print('match1 = {}'.format(match1))
for element in match1:
    print('element = {}'.format(element))
運行結(jié)果:
match1 = ['1', '2', '3']
element = 1
element = 2
element = 3
  • finditer 函數(shù)

finditer 函數(shù)返回指定范圍內(nèi),所有匹配對象構(gòu)成的迭代器。使用過程中只有兩點需要注意一下:
1. 可以指定匹配的范圍,默認范圍是 0 到 len(str)
2. 返回的是一個迭代器,元素是 Match 對象

示例:

import re

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

str1 = 'a1b2c3'

match1 = pattern.finditer(str1)

print('match1 = {}'.format(match1))
for element in match1:
    print('element = {}'.format(element.group()))
運行結(jié)果:
match1 = <callable_iterator object at 0x0000000002CA0550>
element = 1
element = 2
element = 3

比較 findall 和 finditer 函數(shù)的使用:兩個函數(shù)都是獲取所有匹配內(nèi)容,區(qū)別在于 findall 函數(shù)返回的是一個列表,元素類型是 str,finditer 函數(shù)返回的是一個迭代器,元素類型是 Match 。

  • split 函數(shù)

split 函數(shù)返回根據(jù)指定分割次數(shù),分割后得到的結(jié)果列表。使用過程中只有兩點需要注意一下:
1. 可以指定分割次數(shù),默認值 0 表示全分割
2. 返回的是一個列表,元素是 str 對象

示例:

import re

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

str1 = 'a1b2c3'

match1 = pattern.split(str1)

print('match1 = {}'.format(match1))
for element in match1:
    print('element = {}'.format(element))
運行結(jié)果:
match1 = ['a', 'b', 'c', '']
element = a
element = b
element = c
element = 
  • sub 函數(shù)

sub 函數(shù)根據(jù)指定替換規(guī)則和替換次數(shù),返回替換后內(nèi)容。使用過程中只有三點需要注意一下:
1. 可以指定替換次數(shù),默認值 0 表示全替換
2. 返回的是一個 str 對象
3. 指定的替換規(guī)則可以是 str 對象,可以是一個函數(shù),也可以是分組的引用

示例:

import re

def fun(match):
    return match.group()[::-1]

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

str1 = 'a12b34c56'

match1 = pattern.sub('__',str1)
match2 = pattern.sub(fun,str1)
match3 = pattern.sub(r'\2\1',str1)

print('match1 = {}'.format(match1))
print('match2 = {}'.format(match2))
print('match3 = {}'.format(match3))
運行結(jié)果:
match1 = a__b__c__
match2 = a21b43c65
match3 = a21b43c65
  • subn 函數(shù)

subn 函數(shù)根據(jù)指定替換規(guī)則和替換次數(shù),返回替換后內(nèi)容和替換次數(shù)構(gòu)成的元組。使用過程中只有三點需要注意一下:
1. 可以指定替換次數(shù),默認值 0 表示全替換
2. 返回的是一個 str 對象和 int 對象構(gòu)成的元組
3. 指定的替換規(guī)則可以是 str 對象,可以是一個函數(shù),也可以是分組的引用

示例:

import re

def fun(match):
    return match.group()[::-1]

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

str1 = 'a12b34c56'

match1 = pattern.subn('__',str1,1)
match2 = pattern.subn('__',str1,2)


print('match1 = {}'.format(match1))
print('match2 = {}'.format(match2))
運行結(jié)果:
match1 = ('a__b34c56', 1)
match2 = ('a__b__c56', 2)

比較 sub 和 subn 函數(shù)的使用:兩個函數(shù)都是替換匹配內(nèi)容,區(qū)別在于 sub 函數(shù)返回的是一個 str 對象,subn 函數(shù)返回的是替換后 str 對象和替換次數(shù) int 對象構(gòu)成的元組。

下面列出 Match 對象中常到的函數(shù):
函數(shù)名 作用
group(*args) 返回指定的分組匹配的結(jié)果
groups(default=None) 返回所有分組匹配結(jié)果構(gòu)成的元組
span(group=0) 返回由指定分組匹配結(jié)果區(qū)間的首尾兩個下標(biāo)值構(gòu)成的元組
start(group=0) 返回指定分組匹配結(jié)果區(qū)間的首下標(biāo)值
end(group=0) 返回指定分組匹配結(jié)果區(qū)間的尾下標(biāo)值
  • group、groups、span、start、end 函數(shù)

以上這幾個函數(shù)作為常用函數(shù),使用方式較為簡單:
1. group:返回指定分組匹配的內(nèi)容,參數(shù)為零或者默認值時,返回整個正則表達式匹配結(jié)果;參數(shù)為多個分組時,返回分組匹配結(jié)果構(gòu)成的元組
2. groups:返回分組匹配結(jié)果構(gòu)成的元組
3. span:返回指定分組匹配結(jié)果區(qū)間的首尾兩個下標(biāo)值(左閉右開)構(gòu)成的元組,默認情況下匹配整個正則表達式匹配結(jié)果的首尾兩個下標(biāo)值
4. start:返回指定分組匹配結(jié)果區(qū)間的首下標(biāo)
5. end:返回指定分組匹配結(jié)果區(qū)間的尾下標(biāo)

示例:

import re

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

str1 = 'a12b'

match1 = pattern.search(str1)

print('group 1 = {}'.format(match1.group(1)))
print('span 1 = {}'.format(match1.span(1)))
print('start 1 = {}'.format(match1.start(1)))
print('end 1 = {}'.format(match1.end(1)),end='\n\n')

print('group 2 = {}'.format(match1.group(2)))
print('span 2 = {}'.format(match1.span(2)))
print('start 2 = {}'.format(match1.start(2)))
print('end 2 = {}'.format(match1.end(2)),end='\n\n')

print('groups = {}'.format(match1.groups()))
print('span = {}'.format(match1.span()))
print('start = {}'.format(match1.start()))
print('end = {}'.format(match1.end()),end='\n\n')

print('group 1,2 = {}'.format(match1.group(1,2)))
運行結(jié)果:
group 1 = 1
span 1 = (1, 2)
start 1 = 1
end 1 = 2

group 2 = 2
span 2 = (2, 3)
start 2 = 2
end 2 = 3

groups = ('1', '2')
span = (1, 3)
start = 1
end = 3

group 1,2 = ('1', '2')
Pattern 用作模式處理,Match 用作分組結(jié)果提取

比較以上 Pattern 和 Match 兩種對象的使用方式,可以發(fā)現(xiàn) Pattern 對象作用如其名稱所示,是一種體現(xiàn)正則表達式規(guī)則的對象,也就是體現(xiàn)為一種文本模式。其所提供的諸多函數(shù),如: find、search、match 等等,都是拿自身的規(guī)則以不同的方式去處理目標(biāo)文本。而 Match 對象則是對分組結(jié)果的操作,Match 對象提供的函數(shù)則都是對結(jié)果以不同方式的提取,如:groups、span等,獲取匹配分組結(jié)果的各項數(shù)據(jù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Python中的正則表達式(re) import rere.match #從開始位置開始匹配,如果開頭沒有則無re...
    BigJeffWang閱讀 7,559評論 0 99
  • python的re模塊--細說正則表達式 可能是東半球最詳細最全面的re教程,翻譯自官方文檔,因為官方文檔寫的是真...
    立而人閱讀 23,429評論 4 46
  • re模塊手冊 本模塊提供了和Perl里的正則表達式類似的功能,不關(guān)是正則表達式本身還是被搜索的字符串,都可以...
    喜歡吃栗子閱讀 4,184評論 0 13
  • #首先,python中的正則表達式大致分為以下幾部分: 元字符 模式 函數(shù) re 內(nèi)置對象用法 分組用法 環(huán)視用法...
    mapuboy閱讀 1,704評論 0 51
  • 前言 對于正則,著稱火星文字,見名知意主要它晦澀難懂,一直以來,看到它總是怕怕的,在平時,也只是簡單的用用,其主要...
    itclanCoder閱讀 888評論 0 2

友情鏈接更多精彩內(nèi)容