Python中正則表達式
re:re是提供正則表達式匹配操作的模塊
一、什么是正則表達式
正則表達式是一個特殊的字符序列,它能幫助你方便的檢查一個字符串是否與某個模式匹配,Python 自1.5版本起增加了re模塊,它提供Perl風格的正則表達式。
二、正則表達式的基本使用
1、re.match()介紹
match() 試圖從字符串的起始位置對模式進行匹配,如果匹配成功,就返回一個匹配對象,如果匹配失敗,就返回None,匹配對象的group()方法能顯示成功匹配的對象。
使用語法:
re.match(pattern,string[, flags])
參數說明
- 匹配的正則表達式,直接傳入一個字符串,Python會將字符串作為正則表達式來對待
- 匹配的字符串
- 標志位:用於控制正則表達式的匹配方式,如:是否區分大小寫,多行匹配等
import re
ret = re.match("hello","hello word")
print(ret.group()) # 使用group()方式返回對應的分組
注意:
- match() 匹配是從字符串的開始位置匹配,如果開始匹配不到則不在匹配並返回一個None
import re
ret = re.match("hello","ahello word")
print(ret.group()) # 匹配不成功,就返回None
2、re.search()介紹
- re.match() 是從字符串的開始位置匹配,所以基本情況下能夠匹配的概率不大。
- re.search() 是從字符串中搜索正則表達式模式,任何位置都可以被匹配,返回的是第一次出現的匹配對象(因為正則字符串中可能會多出匹配),它的參數和re.match()是一樣的,返回值也是一個匹配對象
使用語法:
re.search(pattern,string[,flags])
import re
ret = re.search("hello","ahello word") # 搜索成功
print(ret.group()) # hello
3、re.match()和re.search()的區別
- re.match匹配的時候只匹配字符串的開始,如果字符串的開始不符合正則表達式,則匹配失敗,函數返回None。
- re.search() 匹配整個字符串,直到匹配到一個。
import re
ret = re.search("^hello","ahello word") # 如果在hello前面加^號,其search的功能和match的功能一樣
print(ret.group()) # 匹配不成功,返回None
4、re.fildall()介紹
- re.fildall() 對整個字符串從左到右進行匹配,返回所有匹配對象的列表.
使用語法:
re.fildall(pattern,string[,flags])
ret = re.fildall('\d+','hello123,word456')
print(ret)
結果:
>>>['123','456']
5、re.compile()介紹
- re.compile() 對整個正則表達式進行預編譯,生成表達式對象,用於正則匹配
使用語法:
re.compile(pattern,flags)
import re
rule = re.compile('\d+')
ret = rule.findall('hellow word456')
print(ret)
>>>456
6、re.split()介紹
- re.split()方法與字符串的切割方法一樣,返回的是一個列表,這了我用正則匹配進行切割
使用語法:
re.split(pattern,string,maxsplit,flags)
import re
strs = 'zhangsan123wangwu345we'
set = re.split('\d+',strs)
print(set)
>>>['zhangsan', 'wangwu', 'we']
7、re.sub()介紹
- re.sub() 批量替換字符串中某個字符,如:將'hello word'替換成'HELLO word'
使用語法:
re.sub(pattern,repl,string,count)
import re
strs = 'hello word'
ret = re.sub('hello','HELLO',strs)
print(ret)
>>>HELLO word
# 使用正則來匹配替換
strs = 'abcd123efg345hi'
ret = re.sub(r'\d+','HELLO',strs)
print(ret)
>>>abcdHELLOefgHELLOhi
8、re.subn()介紹
- re.subn的用法和re.sub是一樣的,區別在與返回值,re.sub返回的是字符串,而re.subn返回的是元組
使用語法:
re.subn(pattern,repl,string,count)
import re
strs = 'abcd123efg345hi'
ret = re.subn(r'\d+','HELLO',strs)
print(ret)
>>>('abcdHELLOefgHELLOhi', 2) #('替換后的字符串',替換的次數)
# 指定替換的次數
import re
strs = 'abcd123efg345hi'
ret = re.subn(r'\d+','HELLO',strs,1)
print(ret)
>>>('abcdHELLOefg345hi', 1)
三、正則表達式語法
- 正則表達式的強大之處是因為它提供了很多特殊符號和字符,使用它們正則表達式才可以強大而又靈活。
字符組
符號 | 描述 |
---|---|
[0-9] | 匹配數字 |
[a-z] | 匹配小寫字母 |
A-Z | 匹配大寫字母 |
[0-9A-z] | 匹配數字及大小寫字母 |
[3-9] | 匹配小范圍的數字值 |
[a-f] | 匹配小范圍的字母值 |
[^abc] | 不匹配abc任意字符 |
[^a-z] | 不匹配a-z直接的任意字符 |
1[0-9] | 匹配10-19直接的數值 |
1[0-9][0-9] | 匹配100-199直接的數值 |
元字符
符號 | 描述 |
---|---|
\d | 匹配固定:0-9數值 |
\w | 匹配數字字母及下划線中文:[0-9A-z_"中文"] |
\s | 匹配空白符:空格,Tab,回車 |
\t | 匹配Tab |
\n | 匹配回車 |
\D | 匹配數字 |
\W | 匹配非數字字母下划線 |
\S | 匹配非空白符 |
. | 匹配除換行符外任意一個字符 |
^ | 匹配以某字符開頭 |
$ | 匹配以某字符結尾 |
[] | 字符組(只要在[]里面的都匹配) |
[^] | 非字符組(只要在[]里面的都不匹配) |
| | 或,(如:abcdef|acb) |
() | 分組,如:^(abcdef|abc)$ |
量詞
符號 | 描述 |
---|---|
{n} | 重復n次 |
{n,} | 重復至少n次,n次以上 |
{n,m} | 重復n-m次 |
? | 0或1次 |
+ | 1到不限 |
* | 0到不限 |
貪婪和惰性
表達式 | 描述 |
---|---|
a.*b | 貪婪 |
a.*?b,a.+?b | 惰性,在量詞后面的?表示惰性匹配,會在符合條件的基礎上盡量少的匹配其他內容 |
貪婪匹配模式
- 用到量詞的匹配時,默認為貪婪模式
- 貪婪模式的意思就是匹配的時候,盡量多匹配,不行再慢慢的減少匹配
import re
lst = "\d{2,4}"
ret = re.search(lst,"12345abcd")
print(ret.group())
結果:
>>>1234
惰性匹配模式
- 惰性匹配模式正好和貪婪模式相對
- 惰性匹配是盡量少的匹配,不行再慢慢去增加匹配的個數
- 惰性匹配只需要在量詞后面添加?即可
import re
lst = "\d{2,4}?"
ret = re.search(lst,"12345abcd")
print(ret.group())
結果:
>>>12
常用正則表達式
表達式 | 描述 | 結果 |
---|---|---|
1[3-9]\d{9} | 匹配手機號 | 13888998899 |
[1-9]\d* | 匹配任意的正整數 | 143 |
\d+.\d+ | 匹配任意小數 | 12.345 |
\d+(.\d+) | 匹配整數或小數 | 12或者12.131231 |
常用分組
代碼 | 描述 |
---|---|
(exp) | 匹配exp,並捕獲文本到自動命名的組里 |
(?exp) | 匹配exp,並捕獲文本到名稱為name的組里,也可以寫(?'name'exp) |
(?:exp) | 匹配exp,不捕獲匹配的文本,也不給次分組分配組號 |
(?=exp) | 匹配exp前面的位置 |
(?<=exp) | 匹配exp后面的位置 |
(?!exp) | 匹配后面跟的不是exp的位置 |
(?<!exp) | 匹配前面不是exp的位置 |
findall,search和分組的關系
案例1:
import re
ret = re.findall('\d(\d)','a1,b22,c345')
print(ret)
>>>[2,4]
案例2:
import re
ret = re.findall('\d(?:\d)','a1,b22,c345')
print(ret)
>>>['22','34']
案例3:
import re
ret = re.search('(?P<num1>\d)(?P<num2>\d)','a14,b22,c3357')
print(ret.group()) # 14
print(ret.group(0)) # 14
print(ret.group(1)) # 1
print(ret.group(2)) # 4
print(ret.group('num1')) # 1
print(ret.group('num2')) # 4
案例4:
import re
ret = re.search('(?P<num1>\d)(?P=num1)','a14,b22,c3357')
print(ret.group()) #匹配10位數,並且分組1=分組2
>>>22
分組的作用
import re
ret = re.search("<(?P<tag_name)>\w)>.*</(?P=tag_name)>","<h1>hello<\h1>")
print(ret)
print(ret.group('tag_name'))
print(ret.group())
>>>h1
>>>h1
>>><h1>hello</h1>