1. 程式人生 > >python3基礎:正則(一)

python3基礎:正則(一)

簡介

正則是一個字串規則,本身也是一個字元型,用來檢查一個串是否含有字串。可以做精確匹配,模糊匹配,進行字串替換,切割,尤其是在造資料,分析日誌時用的非常多。

python中處理正則表示式的模組是re模組,正則表示式由一些普通字元和一些元字元組成,普通字元包括大小寫字母、數字和列印符號,而元字元是具有特殊含義的字元。

正則表示式模式

正則表示式大致的匹配過程是:

拿正則表示式依次和字串或者文字中的字串做比較,如果每一個字元都匹配,則匹配成功,只要有一個匹配不成功的字元,則匹配不成功。模式字串使用特殊的語法來表示一個正則表示式:

  1. 字母和數字匹配它們自身;
  2. 多數字母和數字前加一個反斜槓(\)時會有特殊含義;
  3. 特殊的標點符號,只有被轉義以後才能匹配自身;
  4. 反斜槓本身要用反斜槓來轉義

  注意:

  1. 由於正則表示式通常版本反斜槓等特殊字元,所以最好使用原始字串來表示他們。如:r’\d’等價於’\\d’,表示匹配一個數字
  2. 正則表示式中數量詞預設都是貪婪的,會盡可能多的去匹配滿足的字串,但是如果在後面加上問號’?’,就可以遮蔽貪婪模式,表示匹配儘可能少的字元。如:’xyyyyzs’,使用正則’xy*’,就會得到'xyyyy',如果使用’xy*?’,會得到'x'

 

 特殊表示式含義

符號

含義

舉例

一般字元(匹配自身)

.(點)

匹配除換行符之外的任意一個字元DOTALL模式中可以匹配換行符

a.c可以匹配abc

\(反斜槓)

轉義一個特殊的字元,使這個字元表示原來字面上的意思。如"\$",表示原字元$,而不是正則表示式中表示匹配行尾的意思。

a\.c匹配a.c

預定義字符集(可以寫在[]中)

[...] 方括號

匹配括號中出現的任意單個字元

a[123]b匹配a1b、a2b、a3b、a12b等

[^...]

不匹配方括號中列出的單個字元(注意只能針對單個字元)

[^ab]匹配除a和b之外的字元

\d

匹配中任意一個數字,範圍為[0-9]

a\dc可以匹配a1c、a2c等

\D

匹配任意一個非數字字元,等價於[^\d]

1\D2可匹配1a2

\s

匹配任意一個空白字元:[<空格>\t\r\n\v\f]

a\sf匹配a f

\S

匹配任意一個非空白字元,等價於[^\s]

a\Sg匹配agg等

\w

匹配一個字母或數字,字元範圍:[A-Za-z0-9]

1\wt可以匹配1at等

\W

非單詞字元,等價於[^\w]

a\Wb可以匹配[email protected]

數量字符集(用在字元或分組符(...)之後,非貪婪匹配*? +?)

*(星號)

匹配前一個字元0次1次或多次

abc*可以匹配ab、abc、abcc等

+(加號)

匹配前一個字元1次或多次

cde+可匹配cde、cde等

?(問號)

匹配前一個字元0次或1次

fgh?匹配結果fg、fgh

{m}

匹配前一個字元m次

qc{3}匹配結果qccc

{m,n}

匹配前一個字元m到n次

{m,}匹配前一個字元至少m次

{,n}匹配前一個字元0到n次,最多n次

1{2,5}ac匹配結果11ac、111ac、1111ac、11111ac

 

符號

含義

舉例

 

邊界匹配符

^(託字元)

匹配字串開頭,如果是多行則匹配每一行的開頭。在[...]中,^表示否定,如非字母[^a-zA-Z],非數字[^0-9]

^123匹配123

a[^0-9]b可匹配aab等

 

$(美元符)

匹配字串或一行的結尾,如果是多行則匹配每一行的結尾

abc$匹配abc

 

\A

匹配字串開始,如果存在換行,將字元當作一個整體

\A12AC匹配12AC

 

\b

匹配一個單詞的邊界,也就是指單詞和空格間的位置

\bst匹配a test中的'st',但不匹配'tester'中的''st

\B

[^\b],表示匹配非單詞邊界

\Bst可以匹配'tester'而不能匹配'test'

\Z

匹配字串結束,如果存在換行,將字元當作一個整體

abt\Z匹配abt

 

邏輯匹配符

|(或)

|或匹配符,表達左右正則表示式任意匹配一個。如果左邊的表示式匹配上了,匹配結束,不再匹配右邊的表示式。該符號一般放在()中使用,如果沒在圓括號中則它的範圍是整個正則表示式。

(12|34)匹配12或34

 

分組匹配

(...)

後向引用。用()括起來的正則表示式將被作為一個分組,從正則表示式的左邊依次算起,有多少個左括號'(',就有多少個分組,分組的編碼從1依次加1,無論是括號中巢狀括號。並且分組表示式作為一個整體,後可接數量詞。

(xyz){2}滿足xyzxyz

x(12|34)y匹配x12y或x34y

 

\<number>

引用分組匹配到的分組編號為<number>的字串

如:\1...\9

 

(?P<name>...)

命名分組,除了預設的分組編號外再指定一個別名分組

注意:P是大寫

(?P=name)

引用別名為name的分組匹配,這個是在正則表示式中引用,表示匹配重複的字串,也可以使用編號引用。

注意:P是大寫

特殊匹配符(不能作為分組使用)

(?:...)

(?!pattern)

前向否定斷言語法,表示否定開頭。只能用在正則表示式的開頭,pattern是匹配模式,它後面的內容需要不匹配該正則表示式才匹配成功。

(?<!pattern)

後向否定斷言語法,表示否定結尾,前面的內容需要不匹配該pattern模式才匹配成功。

(?=pattern)

前向肯定斷言語法,需要匹配pattren模式才能匹配成功,表示肯定前面的字元內容。

(?<=pattern)

後向肯定斷言語法,需要匹配pattern模式才能匹配成功,表示肯定後面的字元內容。

(?#...)

#後面的內容將被作為註釋而忽略

.(點)

匹配除換行符之外的所有字元。可以在DOTALL模式中可以匹配換行符。

>>> import re

>>> re.match(r'.','and23__09')

<_sre.SRE_Match object; span=(0, 1), match='a'>#返回的是匹配結果的物件,span表示是是匹配的開始位置和結束位置,開區間



>>> re.match(r'..','and23__09')

<_sre.SRE_Match object; span=(0, 2), match='an'>

>>> re.match(r'..........','and23__09')#匹配的個數比字元中多的時候,返回的是None

>>> print(re.match(r'.','\n'))

None



>>> re.match(r'.','\n',re.DOTALL)#可以匹配換行符

<_sre.SRE_Match object; span=(0, 1), match='\n'>

 

多行字串的兩種實現方式:

三引號

>>> '''hello

... python

... 123'''

'hello\npython\n123'

單引號裡面包含\n

>>> print('abc\ndef')

abc

def

 \(反斜槓)

>>> print(re.match(r"\.",".a\nc"))#匹配 .
<_sre.SRE_Match object; span=(0, 1), match='.'>
>>> print(re.match(r"\\","\\a\nc"))#匹配 \本身
<_sre.SRE_Match object; span=(0, 1), match='\\'>

 

 [...]方括號:

匹配括號中指定的某一個字元,但是隻能匹配一個字元。​​​​​

>>> print(re.match(r"[abc]","axxx")) #匹配字元a
<_sre.SRE_Match object; span=(0, 1), match='a'>
>>> print(re.match(r"[abc]","bxxx")) #匹配字元b
<_sre.SRE_Match object; span=(0, 1), match='b'>
>>> print(re.match(r"[abc]","cxxx"))  #匹配字元c
<_sre.SRE_Match object; span=(0, 1), match='c'>

 

 

[^...]

不匹配括號中指定的任何一個字元,但是隻能匹配一個字元(注意^在方括號裡面表示非,在方括號外面表示開頭匹配)

>>> print(re.match(r"[^abc]","hxxx"))  #匹配開頭是非abc之外的任意一個字元
<_sre.SRE_Match object; span=(0, 1), match='h'>
>>> print(re.search(r"abc","sssssabc")) #匹配abc,可以不是開頭
<_sre.SRE_Match object; span=(5, 8), match='abc'>

>>> print(re.search(r"^abc","sssssabc"))#匹配以abc開頭的字元

None

>>> print(re.match(r"\d","123"))#匹配一次

<_sre.SRE_Match object; span=(0, 1), match='1'>

>>> print(re.match(r"\d+","123"))#匹配一次或多次

<_sre.SRE_Match object; span=(0, 3), match='123'>

>>> print(re.match(r"\d*","123"))#匹配0次或多次

<_sre.SRE_Match object; span=(0, 3), match='123'>

 

 

 \d

匹配中任意一個數字,範圍為[0-9]

>>> re.match(r"\d","123").group()
'1''

 

 

 \D

匹配任意一個非數字字元,等價於[^\d]

>>> re.match(r"\D+","a123").group()
'a'
>>> re.match(r"\D+","abc123").group()
'abc'

 

 \s

匹配任意一個空白字元:[<空格>\t\r\n\v\f]

>>> re.search(r'\s','anb \t \r \n')

<_sre.SRE_Match object; span=(3, 4), match=' '>

>>> re.search(r'\s+','anb \t \r \n')

<_sre.SRE_Match object; span=(3, 9), match=' \t \r \n'>

 

 

 \S

匹配任意一個非空白字元,等價於[^\s]

>>> re.findall(r"\S+","ab cd\t ef\nhi")
['ab', 'cd', 'ef', 'hi']

>>> "".join(re.findall(r"\S+","ab cd\t ef\nhi")) #去掉了字串中所有的空白字元
'abcdefhi'

 

 

 \w

匹配一個字母,數字和下劃線,字元範圍:[A-Za-z0-9_]

>>> re.search(r'\w','12bsc_-')

<_sre.SRE_Match object; span=(0, 1), match='1'>

>>>

>>> re.search(r'\w+','12bsc_-')

<_sre.SRE_Match object; span=(0, 6), match='12bsc_'>

>>>

 \W

非字母,數字和下劃線,等價於[^\w]

>>> re.search(r'\W+','12bsc_-')

<_sre.SRE_Match object; span=(6, 7), match='-'>

>>> re.search(r'\W+','[email protected]')

<_sre.SRE_Match object; span=(1, 2), match='@'>

 

 *

匹配一個字元0次或多次,注意正則預設的貪婪性,貪婪性指的是在滿足匹配的條件下再繼續貪婪更多的匹配

>>> print(re.match(r"\d*","123"))

<_sre.SRE_Match object; span=(0, 3), match='123'>

>>> print(re.match(r"\d*?","123"))  #用問號抑制貪婪,*最小是0次匹配
<_sre.SRE_Match object; span=(0, 0), match=''>
>>> print(re.match(r"\d+?","123"))#用問號抑制貪婪,+最小是1次匹配
<_sre.SRE_Match object; span=(0, 1), match='1'>

>>> print(re.search(r'\d*','abc123'))

<_sre.SRE_Match object; span=(0, 0), match=''>

 search有匹配就會返回,字串不是數字開頭,匹配0次,所以返回的是空

 

 

 ?

匹配一個字元0次或1次,?用在數量詞(*/+/{m}/{m,n})後面才表示抑制貪婪性

>>> re.search(r"\d?","a7").group() #不是以數字開頭,匹配了0次,所以返回空字元

''

>>> re.search(r"\d?","7").group() #以數字開頭,匹配了1次,所以返回7

'7'

 

 

 +

匹配一個字元1次或多次,注意正則預設的貪婪性。

>>> s = "abc123dee"

>>> re.search(r'\d+',s)

<_sre.SRE_Match object; span=(3, 6), match='123'>

>>> re.search(r'\d+',s).group()

'123'

>>> re.search(r"\d+","7").group()

'7'

>>> print(re.match(r"\d+?","123"))#用問號抑制貪婪,+最小是1次匹配
<_sre.SRE_Match object; span=(0, 1), match='1'>

 

 {}

匹配次數

{m}:匹配前一個字元m次

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

{m,}匹配前一個字元至少m次

{,n}匹配前一個字元0到n次,最多n次

>>> re.search(r'\d{2}',"abc123dee").group()

'12'

>>> re.search(r"\d{3}","123456789").group()
'123'
>>> re.search(r"\d{1,3}","123456789").group() #貪婪性
'123'
>>> re.search(r"\d{1,3}?","123456789").group()
'1'

 

 ^(脫字元)

匹配字串開頭,如果是多行則匹配每一行的開頭。在[...]中,^表示否定,如非字母[^a-zA-Z],非數字[^0-9]

>>> re.search(r"^abc","dddabc")

>>> re.search(r"^abc","abcabc")

<_sre.SRE_Match object; span=(0, 3), match='abc'>

>>> re.search(r"^abc","abcde\nabc")

<_sre.SRE_Match object; span=(0, 3), match='abc'>

 

 

 $(美元符)

匹配字串或一行的結尾,如果是多行則匹配每一行的結尾

>>> re.search(r"^\d+","133dddabc")
<_sre.SRE_Match object; span=(0, 3), match='133'>
>>> re.search(r"\d+$","133dddabc5555")
<_sre.SRE_Match object; span=(9, 13), match='5555'>

>>> re.search(r"^123$","123")

<_sre.SRE_Match object; span=(0, 3), match='123'>

 

 

 \A

非多行匹配的時候等價於^,多行匹配的是\A將整個字串看做一個整體匹配,而^能夠則匹配每一行的結尾

>>> re.search(r"\Aabc","abcabc")

<_sre.SRE_Match object; span=(0, 3), match='abc'>

>>> s = '124\n453\n'

>>> re.search(r'^\d',s)

<_sre.SRE_Match object; span=(0, 1), match='1'>

>>> re.findall(r'^\d',s)

['1']

>>> re.findall(r'^\d',s,re.M)  #匹配多行檔案每行的結尾

['1', '4']

>>> re.findall(r'\A\d',s,re.M)  #即使加了re.M,使用\A時仍然是將字串看做一個整體

['1']

>>> re.findall(r'\A\d',s)#使用\A時仍然是將字串看做一個整體

['1']

 \Z

非多行時等價於$,多行匹配\Z將整個字串看做一個整體匹配,而$能夠則匹配每一行的結尾。

>>> re.search(r"\A123\Z","123")

<_sre.SRE_Match object; span=(0, 3), match='123'>



>>> s = '124\n453\n'

>>> re.search(r'\d$',s)

<_sre.SRE_Match object; span=(6, 7), match='3'>

>>> re.search(r'\d\Z',s)  #沒有匹配成功

>>> re.findall(r'\d$',s)

['3']

>>> re.findall(r'\d$',s,re.M) #匹配每一行的結尾

['4', '3']

>>> re.findall(r'\d\Z',s)

[]

>>> re.findall(r'\d\Z',s,re.M)#換行前的結束字元也不能匹配

[]



>>> s = '124\n453'

>>> re.findall(r'\d\Z',s,re.M)

['3']

>>> re.findall(r'\d\Z',s)

['3']

 

 

()分組

用()括起來的正則表示式將被作為一個分組,從正則表示式的左邊依次算起,有多少個左括號'(',就有多少個分組,分組的編碼從1依次加1,無論是括號中巢狀括號。並且分組表示式作為一個整體,後可接數量詞。

>>> re.search(r"\d(\D+)\d","1abc3").group(1)

'abc'

>>> re.search(r"(\d)(\D+)(\d)","1abc3").group(1)

'1'

>>> re.search(r"(\d)(\D+)(\d)","1abc3").group(2)

'abc'

>>> re.search(r"(\d)(\D+)(\d)","1abc3").group(2)

'abc'

>>> re.search(r"(\d)(\D+)(\d)","1abc3").group(3)

'3'

>>> re.search(r"(\d)(\D+)(\d)","1abc3").group()#表示正則表示式匹配的全部內容,等價於group(0)

'1abc3'

>>> re.search(r"(\d)(\D+)(\d)","1abc3").group(0)

'1abc3'