正則表達(dá)式概述
什么是正則表達(dá)式
????正則表達(dá)式:(Regular Expression),是一些有特殊的字符和符號(hào)組成的字符串,主要用來進(jìn)行高級(jí)的文本搜索、匹配、替代等功能。
第一個(gè)正則表達(dá)式
????通過定義一個(gè)簡單的正則表達(dá)式,然后在目標(biāo)字符串中進(jìn)行查詢匹配的操作,完成第一個(gè)程序的編寫,同時(shí)對(duì)于正則表達(dá)式又一個(gè)初步的了解和認(rèn)知。
# 引入正則表達(dá)式模塊
import re
# 目標(biāo)字符串
s = 'food foo tonight'
# 正則表達(dá)式
r = r'foo'
# 在目標(biāo)字符串中查詢符合正則表達(dá)式的字符
res = re.findall(r, s)
# 打印結(jié)果 查詢到兩個(gè)數(shù)據(jù)# ['foo', 'foo']
print(res)
Syntax of Regex(正則表達(dá)式操作語法)
Base Syntax
????正則表達(dá)式的核心就是匹配,匹配用到的也是字符串,對(duì)于正則表達(dá)式的理解就需要對(duì)正則表達(dá)式的語法有一個(gè)比較良好的熟悉度。下面針對(duì)正則表達(dá)式的常見操作,分成三個(gè)部分進(jìn)行了簡要描述,對(duì)正則表達(dá)式語法先有一個(gè)全面的了解。
基本正則語法
| 符號(hào) | 描述 |
|---|---|
| literal | 匹配文本字面值 |
| re1|re2 | 匹配文本字符re1或re2 |
| ^ | 匹配目標(biāo)字符開頭位置 |
| $ | 匹配目標(biāo)字符結(jié)束位置 |
| . | 匹配任意一個(gè)字符(\n除外) |
| ? | 匹配任意一個(gè)字符出現(xiàn)0次或1次 |
| + | 匹配任意一個(gè)字符出現(xiàn)1次或n次 |
| * | 匹配任意一個(gè)字符出現(xiàn)0次或n次 |
| {m} | 匹配任意一個(gè)字符出現(xiàn)m次 |
| {m,} | 匹配任意一個(gè)字符至少出現(xiàn)m次 |
| {,n} | 匹配任意一個(gè)字符最多出現(xiàn)n次 |
| {m,n} | 匹配任意一個(gè)至少出現(xiàn)m次,最多出現(xiàn)n次 |
| [0-9] | 匹配任意一個(gè)0-9之間的數(shù)字 |
| [^0-9] | 匹配任意一個(gè)非數(shù)字字符 |
| [3-6] | 匹配任意一個(gè)3-6之間的數(shù)字 |
| [0-10] | 匹配00或10兩個(gè)數(shù)字 |
| [a-z] | 匹配任意一個(gè)小寫字母 |
| [A-Z] | 匹配任意一個(gè)大寫字符 |
| [a-zA-Z] | 匹配任意一個(gè)字母 |
| [a-zA-Z0-9_] | 匹配任意一個(gè)字母/數(shù)字/下劃線 |
| (..) | 匹配分組表達(dá)式 |
# coding:utf-8
import re
target = '''Are you new to Django or to programming? This is the place to start!
From scratch: Overview | Installation
Tutorial: Part 1: Requests and responses | Part 2: Models and the admin site
| Part 3:
Views and templates | Part 4: Forms and generic views | Part 5: Testing |
Part 6:
Static files | Part 7: Customizing the admin site
Advanced Tutorials: How to write reusable apps | Writing your first patch
for Django
'''
# 基本語法:字符匹配
reg1 = r"to"
print(re.findall(reg1, target))
# ['to', 'to', 'to', 'to', 'to', 'to', 'to']
# 基本語法:或者匹配
reg2 = r"Django|Part"
print(re.findall(reg2, target))
# ['Django', 'Part', 'Part', 'Part', 'Part', 'Part', 'Part', 'Part', 'Django']
# 基本語法:開頭匹配
reg3 = r"^Are"
print(re.findall(reg3, target))
# ['Are']
# 基本語法:結(jié)尾匹配
reg4 = r"Django$"
print(re.findall(reg4, target))
# ['Django']
# 基本語法:任意字符匹配
reg5 = r"Ho."
print(re.findall(reg5, target))
# ['How']
# 基本語法:范圍匹配?,匹配一個(gè)字符出現(xiàn)了0次或1次
reg6 = r"pr?"
print(re.findall(reg6, target))
# ['pr', 'p', 'p', 'p', 'p', 'p', 'p']
# 基本語法:范圍匹配+,匹配一個(gè)字符出現(xiàn)了1次或n次
reg7 = r"pr+"
print(re.findall(reg7, target))
# ['pr']
# 基本語法:范圍匹配*,匹配一個(gè)字符出現(xiàn)了0次或n次
reg8 = r"pr*"
print(re.findall(reg8, target))
# ['pr', 'p', 'p', 'p', 'p', 'p', 'p']
# 基本語法:范圍匹配{m},匹配一個(gè)字符出現(xiàn)了m次
"""
范圍匹配:
{m,n}:匹配一個(gè)字符至少出現(xiàn)m次,至多出現(xiàn)n此
{m,}:匹配一個(gè)字符至少出現(xiàn)m次,至多不限
{,n}:匹配一個(gè)字符至多出現(xiàn)n次,至少不限
"""
reg9 = r"l{2}"
print(re.findall(reg9, target))
# ['ll']
# 基本語法:范圍匹配[0-9],匹配出現(xiàn)了一個(gè)0-9之間的數(shù)字
reg10 = r"[0-9]+"
print(re.findall(reg10, target))
# ['1', '2', '3', '4', '5', '6', '7']
# 基本語法:范圍匹配[a-z]([A-Z]),匹配出現(xiàn)了一個(gè)a-z(A-Z)之間的小寫(大寫)字母
reg11 = r"[a-z]{10}"
print(re.findall(reg11, target))
# ['programmin', 'nstallatio', 'ustomizing']
# 基本語法:范圍匹配[a-zA-Z0-9_],匹配一個(gè)字母、數(shù)字或下劃線
reg12 = r"[a-zA-Z0-9_]{10}"
print(re.findall(reg12, target))
# ['programmin', 'Installati', 'Customizin']
分組查詢
# coding:utf-8
import re
target = '''
<img src="./images/1.jpg"/>
<img src="./images/2.jpg"/>
<img src="./images/3.jpg"/>
<img src="./images/4.jpg"/>
<img src="./images/5.jpg"/>'''
# 正則表達(dá)式中添加分組語法
reg = r'<img\s+src="(.*)"/>'
res = re.finditer(reg, target)
for r in res:
# print(r.group())
print(r.group(1))
正則表達(dá)式:元字符
| 符號(hào) | 描述 |
|---|---|
| \d | 匹配任意一個(gè)[0-9]的數(shù)字 |
| \D | 匹配任意一個(gè)非數(shù)字字符 |
| \s | 匹配任意一個(gè)空白字符(\n\t\r\v\f) |
| \S | 匹配任意一個(gè)非空白字符 |
| \w | 匹配任意一個(gè)字母/數(shù)字/下劃線 |
| \W匹配任意一個(gè)非字母/數(shù)字/下劃線 | |
| \b | 匹配任意一個(gè)單詞的邊界 |
| 轉(zhuǎn)義字符,可以用于匹配正則中用到的字符 |
# coding:utf-8
import re
# 目標(biāo)字符串
target = """Django community 11445 people, 164 countries, 3845 packages and projects."""
# 元字符:\d,匹配任意一個(gè)[0-9]的數(shù)字
reg1 = r"\d+"
print(re.findall(reg1, target))
# ['11445', '164', '3845']
# 元字符:\s,匹配任意一個(gè)空白字符
reg2 = r"\s+"
print(re.findall(reg2, target))
# [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
# 元字符:\b,匹配任意一個(gè)數(shù)字/字母/下劃線
reg3 = r"\w{5}"
print(re.findall(reg3, target))
# ['Djang', 'commu', '11445', 'peopl', 'count', 'packa', 'proje']
# 元字符:,匹配任意一個(gè)單詞的邊界
reg4 = r"\ban."
print(re.findall(reg4, target))
# ['and']
正則表達(dá)式:零寬斷言
| 符號(hào) | 描述 |
|---|---|
| (?reg) | 特殊標(biāo)記參數(shù) |
| (?:reg) | 匹配不用保存的分組 |
| (?P<name>reg) | 匹配到分組結(jié)果命名為name |
| (?P=name) | 注釋(?P<name>reg)前的文本 |
| (?#content) | 注釋 |
| (?=reg) | 正向前視斷言 |
| (?!reg) | 負(fù)向前視斷言 |
| (?<=reg) | 正向后視斷言 |
| (?<!reg) | 負(fù)向后視斷言 |
| (?(id/name)Yre1/Nre2) | 條件斷言分組 |
# coding:utf-8
import re
# 目標(biāo)字符串
target = 'aahelloworldbbhellojerryjerryup'
# 零寬斷言:正向前視斷言
reg1 = r'.{2}hello(?=world)'
res = re.finditer(reg1, target)
for r in res:
print(r.group()) # aahello
reg2 = r'.{2}hello(?!world)'
res = re.finditer(reg2, target)
for r in res:
print(r.group()) # bbhello
reg3 = r'(?<=hello)jerry.{2}'
res = re.finditer(reg3, target)
for r in res:
print(r.group()) # jerryje
reg4 = r'(?<!hello)jerry.{2}'
res = re.finditer(reg4, target)
for r in res:
print(r.group()) # jerryup
貪婪匹配 & 懶惰匹配
????貪婪模式和懶惰模式(非貪婪模式)是在正則操作過程中,需要嚴(yán)格注意的一個(gè)問題,如果操作不當(dāng)?shù)脑捄苋菀自谄ヅ溥^程中得到非正常數(shù)據(jù)或者垃圾數(shù)據(jù)。
什么是貪婪和非貪婪模式
貪婪模式:在正則表達(dá)式匹配成功的前提下,盡可能多的匹配結(jié)果數(shù)據(jù)
非貪婪模式:在正則表達(dá)式匹配成功的前提下,盡可能少的匹配結(jié)果數(shù)據(jù)
貪婪和非貪婪模式
# coding:utf-8
import re
target = "<div>hello</div><p>world</p><div>regular expression</div>"
# 正則表達(dá)式:貪婪匹配
reg = re.compile(r"<div>.*</div>")
# 查詢數(shù)據(jù)
res = reg.search(target)
print(res.group())
# <div>hello</div><p>world</p><div>regular expression</div>
# 正則表達(dá)式:懶惰匹配(非貪婪匹配)
reg = re.compile(r"<div>.*?</div>")
# 查詢數(shù)據(jù)
res = reg.search(target)
print(res.group())
# <div>hello</div>
pyhton中的正則
re正則模塊
python中通過標(biāo)準(zhǔn)庫re模塊對(duì)于正則表達(dá)式進(jìn)行良好的技術(shù)支持。
為什么使用正則表達(dá)式
????正則表達(dá)式本身就是對(duì)于字符串的高效處理,盡管字符串本身也內(nèi)置了一些操作函數(shù),但是相對(duì)于較為復(fù)雜的需求,通過正則表達(dá)式的操作更加靈活并且效率更高。
????正則表達(dá)式在程序中的主要應(yīng)用,有以下幾個(gè)方面:
????????匹配:測(cè)試一個(gè)字符串是否符合正則表達(dá)式語法,返回 True 或者 False
????????獲?。簭哪繕?biāo)字符串中,提取符合正則表達(dá)式語法的字符數(shù)據(jù)
????????替換:在目標(biāo)字符串中查詢符合正則語法的字符,并替換成指定的字符串
????????分割:按照符合正則表達(dá)式的語法字符對(duì)目標(biāo)字符串進(jìn)行分割
創(chuàng)建正則表達(dá)式的方式
????python中有兩種方式可以創(chuàng)建正則表達(dá)式的匹配對(duì)象,兩種方式使用都較為廣泛,具體滿足開發(fā)人員所在的團(tuán)隊(duì)的開發(fā)規(guī)范即可。
隱式創(chuàng)建:通過一個(gè)普通字符串,直接創(chuàng)建正則表達(dá)式
要求:必須通過re模塊的函數(shù)調(diào)用才能正常編譯執(zhí)行
import re
# 創(chuàng)建一個(gè)正則表達(dá)式
reg = r"\bfoo\b"
# 從目標(biāo)字符串中提取數(shù)據(jù)
result = re.findall(reg, target_str)
顯式創(chuàng)建:通過內(nèi)建函數(shù)compile()編譯創(chuàng)建一個(gè)正則表達(dá)式對(duì)象
要求:可以通過調(diào)用該類型的方法,完成字符串的操作
import re
pattern = re.compile("\\bfoo\\b")
pattern.findall(target_str)
簡要操作案例
# coding:utf-8
import re
target = "helloworldhelloregexp"
# 1.函數(shù)
reg1 = r"(?<=hello).{3}"
print(re.findall(reg1, target))
# ['wor', 'reg']
# 2.對(duì)象
reg2 = re.compile(r"(?<=hello).{3}")
print(reg2.findall(target))
# ['wor', 'reg']
re模塊常用方法
常用方法
| 常用方法 | 描述 |
|---|---|
| re.findall(s, start, end) | 返回(指定位置)查詢到結(jié)果內(nèi)容的列表 |
| re.finditer(s, start, end) | 返回(指定位置)查詢到結(jié)果匹配對(duì)象的生成器 |
| re.search(s, start, end) | 返回(指定位置)第一次查詢到的匹配對(duì)象 |
| re.match(s, start, end) | 返回(指定位置)從第一個(gè)字符匹配到的結(jié)果 |
| re.sub(s, r, c) | 使用r替換字符串中所有匹配的數(shù)據(jù),c是替換次數(shù) |
| re.subn(s, r, c) | 使用r替換字符串中所有匹配的數(shù)據(jù),c是替換次數(shù) |
| re.split(s, m) | 使用正則表達(dá)式拆分字符串,m是拆分次數(shù) |
簡單示例
# coding:utf-8
import re
target = "helloworldhellojerryhelloregularexpression"
# 定義正則表達(dá)式
reg = r"hello"
# findall()
print(re.findall(reg, target))
# ['hello', 'hello', 'hello']
# finditer()
res = re.finditer(reg, target)
for r in res:
print(r.group())
# hello
# hello
# hello
# search()
res = re.search(reg, target)
print(res)
# <_sre.SRE_Match object; span=(0, 5), match='hello'>
# match()
res = re.match(reg, target)
print(res)
# <_sre.SRE_Match object; span=(0, 5), match='hello'>
# sub()
res = re.sub(reg, "**", target)
print(res)
# **world**jerry**regularexpression
# subn()
res = re.subn(reg, "**", target)
print(res)
# ('**world**jerry**regularexpression', 3)
# split()
res = re.split(reg, target)
print(res)
# ['', 'world', 'jerry', 'regularexpression']