日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python正则匹配_python 正则表达式详解

發布時間:2025/3/20 python 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python正则匹配_python 正则表达式详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正則表達式是一個很強大的字符串處理工具,幾乎任何關于字符串的操作都可以使用正則表達式來完成,作為一個爬蟲工作者,每天和字符串打交道,正則表達式更是不可或缺的技能,正則表達式的在不同的語言中使用方式可能不一樣,不過只要學會了任意一門語言的正則表達式用法,其他語言中大部分也只是換了個函數的名稱而已,本質都是一樣的。下面,我來介紹一下python中的正則表達式是怎么使用的。

首先,python中的正則表達式大致分為以下幾部分:

元字符

模式

函數

re 內置對象用法

分組用法

環視用法

所有關于正則表達式的操作都使用 python 標準庫中的 re 模塊。

一、元字符 (參見 python 模塊 re 文檔)

. 匹配任意字符(不包括換行符)

^ 匹配開始位置,多行模式下匹配每一行的開始

$ 匹配結束位置,多行模式下匹配每一行的結束

* 匹配前一個元字符0到多次

+ 匹配前一個元字符1到多次

? 匹配前一個元字符0到1次

{m,n} 匹配前一個元字符m到n次

\\ 轉義字符,跟在其后的字符將失去作為特殊元字符的含義,例如\\.只能匹配.,不能再匹配任意字符

[] 字符集,一個字符的集合,可匹配其中任意一個字符

| 邏輯表達式 或 ,比如 a|b 代表可匹配 a 或者 b

(...) 分組,默認為捕獲,即被分組的內容可以被單獨取出,默認每個分組有個索引,從 1 開始,按照"("的順序決定索引值

(?iLmsux) 分組中可以設置模式,iLmsux之中的每個字符代表一個模式,用法參見 模式 I

(?:...) 分組的不捕獲模式,計算索引時會跳過這個分組

(?P...) 分組的命名模式,取此分組中的內容時可以使用索引也可以使用name

(?P=name) 分組的引用模式,可在同一個正則表達式用引用前面命名過的正則

(?#...) 注釋,不影響正則表達式其它部分,用法參見 模式 I

(?=...) 順序肯定環視,表示所在位置右側能夠匹配括號內正則

(?!...) 順序否定環視,表示所在位置右側不能匹配括號內正則

(?<=...) 逆序肯定環視,表示所在位置左側能夠匹配括號內正則

(?

(?(id/name)yes|no) 若前面指定id或name的分區匹配成功則執行yes處的正則,否則執行no處的正則

\number 匹配和前面索引為number的分組捕獲到的內容一樣的字符串

\A 匹配字符串開始位置,忽略多行模式

\Z 匹配字符串結束位置,忽略多行模式

\b 匹配位于單詞開始或結束位置的空字符串

\B 匹配不位于單詞開始或結束位置的空字符串

\d 匹配一個數字, 相當于 [0-9]

\D 匹配非數字,相當于 [^0-9]

\s 匹配任意空白字符, 相當于 [ \t\n\r\f\v]

\S 匹配非空白字符,相當于 [^ \t\n\r\f\v]

\w 匹配數字、字母、下劃線中任意一個字符, 相當于 [a-zA-Z0-9_]

\W 匹配非數字、字母、下劃線中的任意字符,相當于 [^a-zA-Z0-9_]

二、模式

I IGNORECASE, 忽略大小寫的匹配模式, 樣例如下

s = 'hello World!'

regex = re.compile("hello world!", re.I)

print regex.match(s).group()

#output> 'Hello World!'

#在正則表達式中指定模式以及注釋

regex = re.compile("(?#注釋)(?i)hello world!")

print regex.match(s).group()

#output> 'Hello World!'

L LOCALE, 字符集本地化。這個功能是為了支持多語言版本的字符集使用環境的,比如在轉義符\w,在英文環境下,它代表[a-zA-Z0-9_],即所以英文字符和數字。如果在一個法語環境下使用,缺省設置下,不能匹配"é" 或 "?"。加上這L選項和就可以匹配了。不過這個對于中文環境似乎沒有什么用,它仍然不能匹配中文字符。

M MULTILINE,多行模式, 改變 ^ 和 $ 的行為

s = '''first line

second line

third line'''

# ^

regex_start = re.compile("^\w+")

print regex_start.findall(s)

# output> ['first']

regex_start_m = re.compile("^\w+", re.M)

print regex_start_m.findall(s)

# output> ['first', 'second', 'third']

#$

regex_end = re.compile("\w+$")

print regex_end.findall(s)

# output> ['line']

regex_end_m = re.compile("\w+$", re.M)

print regex_end_m.findall(s)

# output> ['line', 'line', 'line']

S  DOTALL,此模式下 '.' 的匹配不受限制,可匹配任何字符,包括換行符

s = '''first line

second line

third line'''

#

regex = re.compile(".+")

print regex.findall(s)

# output> ['first line', 'second line', 'third line']

# re.S

regex_dotall = re.compile(".+", re.S)

print regex_dotall.findall(s)

# output> ['first line\nsecond line\nthird line']

X VERBOSE,冗余模式, 此模式忽略正則表達式中的空白和#號的注釋,例如寫一個匹配郵箱的正則表達式

email_regex = re.compile("[\w+\.]+@[a-zA-Z\d]+\.(com|cn)")

email_regex = re.compile("""[\w+\.]+ # 匹配@符前的部分

@ # @符

[a-zA-Z\d]+ # 郵箱類別

\.(com|cn) # 郵箱后綴 """, re.X)

U UNICODE,使用 \w, \W, \b, \B 這些元字符時將按照 UNICODE 定義的屬性.

正則表達式的模式是可以同時使用多個的,在 python 里面使用按位或運算符 | 同時添加多個模式

如 re.compile('', re.I|re.M|re.S)

每個模式在 re 模塊中其實就是不同的數字

print re.I

# output> 2

print re.L

# output> 4

print re.M

# output> 8

print re.S

# output> 16

print re.X

# output> 64

print re.U

# output> 32

三、函數 (參見 python 模塊 re 文檔)

python 的 re 模塊提供了很多方便的函數使你可以使用正則表達式來操作字符串,每種函數都有它自己的特性和使用場景,熟悉之后對你的工作會有很大幫助

compile(pattern, flags=0)

給定一個正則表達式 pattern,指定使用的模式 flags 默認為0 即不使用任何模式,然后會返回一個 SRE_Pattern (參見 第四小節 re 內置對象用法) 對象

regex = re.compile(".+")

print regex

# output> <_sre.SRE_Pattern object at 0x00000000026BB0B8>

這個對象可以調用其他函數來完成匹配,一般來說推薦使用 compile 函數預編譯出一個正則模式之后再去使用,這樣在后面的代碼中可以很方便的復用它,當然大部分函數也可以不用 compile 直接使用,具體見 findall 函數

s = '''first line

second line

third line'''

#

regex = re.compile(".+")

# 調用 findall 函數

print regex.findall(s)

# output> ['first line', 'second line', 'third line']

# 調用 search 函數

print regex.search(s).group()

# output> first lin

escape(pattern)

轉義 如果你需要操作的文本中含有正則的元字符,你在寫正則的時候需要將元字符加上反斜扛 \ 去匹配自身, 而當這樣的字符很多時,寫出來的正則表達式就看起來很亂而且寫起來也挺麻煩的,這個時候你可以使用這個函數,用法如下

s = ".+\d123"

#

regex_str = re.escape(".+\d123")

# 查看轉義后的字符

print regex_str

# output> \.\+\\d123

# 查看匹配到的結果

for g in re.findall(regex_str, s):

print g

# output> .+\d123

findall(pattern, string, flags=0)

參數 pattern 為正則表達式, string 為待操作字符串, flags 為所用模式,函數作用為在待操作字符串中尋找所有匹配正則表達式的字串,返回一個列表,如果沒有匹配到任何子串,返回一個空列表。

s = '''first line

second line

third line'''

# compile 預編譯后使用 findall

regex = re.compile("\w+")

print regex.findall(s)

# output> ['first', 'line', 'second', 'line', 'third', 'line']

# 不使用 compile 直接使用 findall

print re.findall("\w+", s)

# output> ['first', 'line', 'second', 'line', 'third', 'line']

finditer(pattern, string, flags=0)

參數和作用與 findall 一樣,不同之處在于 findall 返回一個列表, finditer 返回一個迭代器(參見 http://www.cnblogs.com/huxi/archive/2011/07/01/2095931.html ), 而且迭代器每次返回的值并不是字符串,而是一個 SRE_Match (參見 第四小節 re 內置對象用法) 對象,這個對象的具體用法見 match 函數。

s = '''first line

second line

third line'''

regex = re.compile("\w+")

print regex.finditer(s)

# output>

for i in regex.finditer(s):

print i

# output> <_sre.SRE_Match object at 0x0000000002B7A920>

# <_sre.SRE_Match object at 0x0000000002B7A8B8>

# <_sre.SRE_Match object at 0x0000000002B7A920>

# <_sre.SRE_Match object at 0x0000000002B7A8B8>

# <_sre.SRE_Match object at 0x0000000002B7A920>

# <_sre.SRE_Match object at 0x0000000002B7A8B8>

match(pattern, string, flags=0)

使用指定正則去待操作字符串中尋找可以匹配的子串, 返回匹配上的第一個字串,并且不再繼續找,需要注意的是 match 函數是從字符串開始處開始查找的,如果開始處不匹配,則不再繼續尋找,返回值為 一個 SRE_Match(參見 第四小節 re 內置對象用法) 對象,找不到時返回 None

s = '''first line

second line

third line'''

# compile

regex = re.compile("\w+")

m = regex.match(s)

print m

# output> <_sre.SRE_Match object at 0x0000000002BCA8B8>

print m.group()

# output> first

# s 的開頭是 "f", 但正則中限制了開始為 i 所以找不到

regex = re.compile("^i\w+")

print regex.match(s)

# output> None

purge()

當你在程序中使用 re 模塊,無論是先使用 compile 還是直接使用比如 findall 來使用正則表達式操作文本,re 模塊都會將正則表達式先編譯一下, 并且會將編譯過后的正則表達式放到緩存中,這樣下次使用同樣的正則表達式的時候就不需要再次編譯, 因為編譯其實是很費時的,這樣可以提升效率,而默認緩存的正則表達式的個數是 100, 當你需要頻繁使用少量正則表達式的時候,緩存可以提升效率,而使用的正則表達式過多時,緩存帶來的優勢就不明顯了 (參考 《python re.compile對性能的影響》http://blog.trytofix.com/article/detail/13/), 這個函數的作用是清除緩存中的正則表達式,可能在你需要優化占用內存的時候會用到。

search(pattern, string, flags=0)

函數類似于 match,不同之處在于不限制正則表達式的開始匹配位置

s = '''first line

second line

third line'''

# 需要從開始處匹配 所以匹配不到

print re.match('i\w+', s)

# output> None

# 沒有限制起始匹配位置

print re.search('i\w+', s)

# output> <_sre.SRE_Match object at 0x0000000002C6A920>

print re.search('i\w+', s).group()

# output> irst

split(pattern, string, maxsplit=0, flags=0)

參數 maxsplit 指定切分次數, 函數使用給定正則表達式尋找切分字符串位置,返回包含切分后子串的列表,如果匹配不到,則返回包含原字符串的一個列表

s = '''first 111 line

second 222 line

third 333 line'''

# 按照數字切分

print re.split('\d+', s)

# output> ['first ', ' line\nsecond ', ' line\nthird ', ' line']

# \.+ 匹配不到 返回包含自身的列表

print re.split('\.+', s, 1)

# output> ['first 111 line\nsecond 222 line\nthird 333 line']

# maxsplit 參數

print re.split('\d+', s, 1)

# output> ['first ', ' line\nsecond 222 line\nthird 333 line']

sub(pattern, repl, string, count=0, flags=0)

替換函數,將正則表達式 pattern 匹配到的字符串替換為 repl 指定的字符串, 參數 count 用于指定最大替換次數

s = "the sum of 7 and 9 is [7+9]."

# 基本用法 將目標替換為固定字符串

print re.sub('\[7\+9\]', '16', s)

# output> the sum of 7 and 9 is 16.

# 高級用法 1 使用前面匹配的到的內容 \1 代表 pattern 中捕獲到的第一個分組的內容

print re.sub('\[(7)\+(9)\]', r'\2\1', s)

# output> the sum of 7 and 9 is 97.

# 高級用法 2 使用函數型 repl 參數, 處理匹配到的 SRE_Match 對象

def replacement(m):

p_str = m.group()

if p_str == '7':

return '77'

if p_str == '9':

return '99'

return ''

print re.sub('\d', replacement, s)

# output> the sum of 77 and 99 is [77+99].

# 高級用法 3 使用函數型 repl 參數, 處理匹配到的 SRE_Match 對象 增加作用域 自動計算

scope = {}

example_string_1 = "the sum of 7 and 9 is [7+9]."

example_string_2 = "[name = 'Mr.Gumby']Hello,[name]"

def replacement(m):

code = m.group(1)

st = ''

try:

st = str(eval(code, scope))

except SyntaxError:

exec code in scope

return st

# 解析: code='7+9'

# str(eval(code, scope))='16'

print re.sub('\[(.+?)\]', replacement, example_string_1)

# output> the sum of 7 and 9 is 16.

# 兩次替換

# 解析1: code="name = 'Mr.Gumby'"

# eval(code)

# raise SyntaxError

# exec code in scope

# 在命名空間 scope 中將 "Mr.Gumby" 賦給了變量 name

# 解析2: code="name"

# eval(name) 返回變量 name 的值 Mr.Gumby

print re.sub('\[(.+?)\]', replacement, example_string_2)

# output> Hello,Mr.Gumby

subn(pattern, repl, string, count=0, flags=0)

作用與函數 sub 一樣, 唯一不同之處在于返回值為一個元組,第一個值為替換后的字符串,第二個值為發生替換的次數

template(pattern, flags=0)

這個吧,咋一看和 compile 差不多,不過不支持 +、?、*、{} 等這樣的元字符,只要是需要有重復功能的元字符,就不支持,查了查資料,貌似沒人知道這個函數到底是干嘛的...

四、re 內置對象用法

SRE_Pattern 這個對象是一個編譯后的正則表達式,編譯后不僅能夠復用和提升效率,同時也能夠獲得一些其他的關于正則表達式的信息

屬性:

flags 編譯時指定的模式

groupindex 以正則表達式中有別名的組的別名為鍵、以該組對應的編號為值的字典,沒有別名的組不包含在內。

groups 正則表達式中分組的數量

pattern 編譯時用的正則表達式

s = 'Hello, Mr.Gumby : 2016/10/26'

p = re.compile('''(?: # 構造一個不捕獲分組 用于使用 |

(?P\w+\.\w+) # 匹配 Mr.Gumby

| # 或

(?P\s+\.\w+) # 一個匹配不到的命名分組

)

.*? # 匹配 :

(\d+) # 匹配 2016

''', re.X)

#

print p.flags

# output> 64

print p.groupindex

# output> {'name': 1, 'no': 2}

print p.groups

# output> 3

print p.pattern

# output> (?: # 構造一個不捕獲分組 用于使用 |

# (?P\w+\.\w+) # 匹配 Mr.Gumby

# | # 或

# (?P\s+\.\w+) # 一個匹配不到的命名分組

# )

# .*? # 匹配 :

# (\d+) # 匹配 2016

函數:可使用 findall、finditer、match、search、split、sub、subn 等函數

SRE_Match 這個對象會保存本次匹配的結果,包含很多關于匹配過程以及匹配結果的信息

屬性:

endpos 本次搜索結束位置索引

lastgroup 本次搜索匹配到的最后一個分組的別名

lastindex 本次搜索匹配到的最后一個分組的索引

pos 本次搜索開始位置索引

re 本次搜索使用的 SRE_Pattern 對象

regs 列表,元素為元組,包含本次搜索匹配到的所有分組的起止位置

string 本次搜索操作的字符串

s = 'Hello, Mr.Gumby : 2016/10/26'

m = re.search(', (?P\w+\.\w+).*?(\d+)', s)

# 本次搜索的結束位置索引

print m.endpos

# output> 28

# 本次搜索匹配到的最后一個分組的別名

# 本次匹配最后一個分組沒有別名

print m.lastgroup

# output> None

# 本次搜索匹配到的最后一個分組的索引

print m.lastindex

# output> 2

# 本次搜索開始位置索引

print m.pos

# output> 0

# 本次搜索使用的 SRE_Pattern 對象

print m.re

# output> <_sre.SRE_Pattern object at 0x000000000277E158>

# 列表,元素為元組,包含本次搜索匹配到的所有分組的起止位置 第一個元組為正則表達式匹配范圍

print m.regs

# output> ((7, 22), (7, 15), (18, 22))

# 本次搜索操作的字符串

print m.string

# output> Hello, Mr.Gumby : 2016/10/26

函數:

end([group=0]) 返回指定分組的結束位置,默認返回正則表達式所匹配到的最后一個字符的索引

expand(template) 根據模版返回相應的字符串,類似與 sub 函數里面的 repl, 可使用 \1 或者 \g 來選擇分組

group([group1, ...]) 根據提供的索引或名字返回響應分組的內容,默認返回 start() 到 end() 之間的字符串, 提供多個參數將返回一個元組

groupdict([default=None]) 返回 返回一個包含所有匹配到的命名分組的字典,沒有命名的分組不包含在內,key 為組名, value 為匹配到的內容,參數 default 為沒有參與本次匹配的命名分組提供默認值

groups([default=None]) 以元組形式返回每一個分組匹配到的字符串,包括沒有參與匹配的分組,其值為 default

span([group]) 返回指定分組的起止位置組成的元組,默認返回由 start() 和 end() 組成的元組

start([group]) 返回指定分組的開始位置,默認返回正則表達式所匹配到的第一個字符的索引

s = 'Hello, Mr.Gumby : 2016/10/26'

m = re.search('''(?: # 構造一個不捕獲分組 用于使用 |

(?P\w+\.\w+) # 匹配 Mr.Gumby

| # 或

(?P\s+\.\w+) # 一個匹配不到的命名分組

)

.*? # 匹配 :

(\d+) # 匹配 2016

''',

s, re.X)

# 返回指定分組的結束位置,默認返回正則表達式所匹配到的最后一個字符的索引

print m.end()

# output> 22

# 根據模版返回相應的字符串,類似與 sub 函數里面的 repl, 可使用 \1 或者 \g 來選擇分組

print m.expand("my name is \\1")

# output> my name is Mr.Gumby

# 根據提供的索引或名字返回響應分組的內容,默認返回 start() 到 end() 之間的字符串, 提供多個參數將返回一個元組

print m.group()

# output> Mr.Gumby : 2016

print m.group(1,2)

# output> ('Mr.Gumby', None)

# 返回 返回一個包含所有匹配到的命名分組的字典,沒有命名的分組不包含在內,key 為組名, value 為匹配到的內容,參數 default 為沒有參與本次匹配的命名分組提供默認值

print m.groupdict('default_string')

# output> {'name': 'Mr.Gumby', 'no': 'default_string'}

# 以元組形式返回每一個分組匹配到的字符串,包括沒有參與匹配的分組,其值為 default

print m.groups('default_string')

# output> ('Mr.Gumby', 'default_string', '2016')

# 返回指定分組的起止未知組成的元組,默認返回由 start() 和 end() 組成的元組

print m.span(3)

# output> (18, 22)

# 返回指定分組的開始位置,默認返回正則表達式所匹配到的第一個字符的索引

print m.start(3)

# output> 18

五、分組用法

python 的正則表達式中用小括號 "(" 表示分組,按照每個分組中前半部分出現的順序 "(" 判定分組的索引,索引從 1 開始,每個分組在訪問的時候可以使用索引,也可以使用別名

s = 'Hello, Mr.Gumby : 2016/10/26'

p = re.compile("(?P\w+\.\w+).*?(\d+)(?#comment)")

m = p.search(s)

# 使用別名訪問

print m.group('name')

# output> Mr.Gumby

# 使用分組訪問

print m.group(2)

# output> 2016

有時候可能只是為了把正則表達式分組,而不需要捕獲其中的內容,這時候可以使用非捕獲分組

s = 'Hello, Mr.Gumby : 2016/10/26'

p = re.compile("""

(?: # 非捕獲分組標志 用于使用 |

(?P\w+\.\w+)

|

(\d+/)

)

""", re.X)

m = p.search(s)

# 使用非捕獲分組

# 此分組將不計入 SRE_Pattern 的 分組計數

print p.groups

# output> 2

# 不計入 SRE_Match 的分組

print m.groups()

# output> ('Mr.Gumby', None)

如果你在寫正則的時候需要在正則里面重復書寫某個表達式,那么你可以使用正則的引用分組功能,需要注意的是引用的不是前面分組的 正則表達式而是捕獲到的 內容,并且引用的分組不算在分組總數中.

s = 'Hello, Mr.Gumby : 2016/2016/26'

p = re.compile("""

(?: # 非捕獲分組標志 用于使用 |

(?P\w+\.\w+)

|

(\d+/)

)

.*?(?P\d+)/(?P=number)/

""", re.X)

m = p.search(s)

# 使用引用分組

# 此分組將不計入 SRE_Pattern 的 分組計數

print p.groups

# output> 3

# 不計入 SRE_Match 的分組

print m.groups()

# output> ('Mr.Gumby', None, '2016')

# 查看匹配到的字符串

print m.group()

# output> Mr.Gumby : 2016/2016/

六、環視用法

環視還有其他的名字,例如 界定、斷言、預搜索等,叫法不一。

環視是一種特殊的正則語法,它匹配的不是字符串,而是 位置,其實就是使用正則來說明這個位置的左右應該是什么或者應該不是什么,然后去尋找這個位置。

環視的語法有四種,見第一小節元字符,基本用法如下。

s = 'Hello, Mr.Gumby : 2016/10/26 Hello,r.Gumby : 2016/10/26'

# 不加環視限定

print re.compile("(?P\w+\.\w+)").findall(s)

# output> ['Mr.Gumby', 'r.Gumby']

# 環視表達式所在位置 左邊為 "Hello, "

print re.compile("(?<=Hello, )(?P\w+\.\w+)").findall(s)

# output> ['Mr.Gumby']

# 環視表達式所在位置 左邊不為 ","

print re.compile("(?\w+\.\w+)").findall(s)

# output> ['Mr.Gumby']

# 環視表達式所在位置 右邊為 "M"

print re.compile("(?=M)(?P\w+\.\w+)").findall(s)

# output> ['Mr.Gumby']

# 環視表達式所在位置 右邊不為 r

print re.compile("(?!r)(?P\w+\.\w+)").findall(s)

# output> ['Mr.Gumby']

參考文章:

總結

以上是生活随笔為你收集整理的python正则匹配_python 正则表达式详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。