(十九)Python中級知識-正則表達式(re模塊)

1、概述

正則表達式(英語:Regular Expression,常簡寫爲regex、regexp或RE),又稱正則表示式、正則表示法、規則表達式、常規表示法,是計算機科學的一個概念。正則表達式使用單個字符串來描述、匹配一系列符合某個句法規則的字符串。

許多程序設計語言都支持利用正則表達式進行字符串操作。同樣,在python中就內建了一個功能強大的正則表達式引擎。

我們在普通的操作中已經可以拼接追加甚至替換字符串等基本操作了,但是當我們需要進行字符串查找、一些以某幾個字符開頭的字符串查找、及只提取字符串中的數字,等等帶有一定規則匹配的字符串,常規的操作就不是那麼好處理了。

但是,通過使用正則表達式我們就可以很方便的進行操作,而且速度也很快。這也可理解爲正則表達式的巨大作用。

運行正則表達式需要程序設計語言集成正則表達式引擎,只有在這個引擎上纔可以解析正則表達式,Python編譯環境就自動集成了此引擎,所以我們可以直接在python代碼中使用正則表達式。

正則表達式長什麼樣?

表達式 描述
\D 匹配一個非數字字符。等價於 [^0-9],不是0到9的數字。
#.*$ 匹配#這個字符串後的所有字符
z* 匹配*號前面的子表達式零次或多次出現的字符串

更多的正則表達式的介紹可以參考此鏈接:正則表達式

在Python中如何使用正則表達式?
首先我們需要導入對應的模塊。

import re

2、關鍵函數

本文主要用到了如下關鍵函數:

名稱 描述
re.match(pattern, string, flags=0) 匹配到了正則表達式,就返回一個相應的 匹配對象 。 如果沒有匹配,就返回 None 。無論是單行還是多行模式, re.match() 也只匹配字符串的開始位置,而不匹配每行開始
re.search(pattern, string, flags=0) 掃描整個 字符串 找到匹配樣式的第一個位置,並返回一個相應的 匹配對象。如果沒有匹配,就返回一個 None ;
re.sub(pattern, repl, string, count=0, flags=0) 返回通過使用 repl 替換在 string 最左邊非重疊出現的 pattern 而獲得的字符串。
re.compile(pattern, flags=0) 將正則表達式的樣式編譯爲一個 正則表達式對象 (正則對象)。
re.finditer(pattern, string, flags=0) pattern 在 string 裏所有的非重複匹配,返回爲一個迭代器 iterator 保存了 匹配對象 。 string 從左到右掃描,匹配按順序排列。空匹配也包含在結果裏。
re.split(pattern, string, maxsplit=0, flags=0) 用 pattern 分開 string 。 如果在 pattern 中捕獲到括號,那麼所有的組裏的文字也會包含在列表裏。如果 maxsplit 非零, 最多進行 maxsplit 次分隔, 剩下的字符全部返回到列表的最後一個元素。

flags這個參數可以設置的值如下:

  • .* 表示任意匹配除換行符(\n、\r)之外的任何單個或多個字符
  • re.I 使匹配對大小寫不敏感
  • re.L 做本地化識別(locale-aware)匹配
  • re.M 多行匹配,影響 ^ 和 $
  • re.S 使 . 匹配包括換行在內的所有字符
  • re.U 根據Unicode字符集解析字符。這個標誌影響 \w, \W, \b, \B.
  • re.X 該標誌通過給予你更靈活的格式以便你將正則表達式寫得更易於理解。
    flags可以通過|符合並聯多個。

其實上面這表看起來比較複雜,實際上在案例裏面進行操作會更容易理解。

3、案例

import re

# 返回一個元組包含匹配(開始,結束) 的位置
print(re.match('www', 'www.baidu.com').span())
# re.match 只會從第一個位置開始匹配,如果沒找到則直接返回None
print(re.match('c', 'www.baidu.com'))

line = "This is your life!"
# .* 表示任意匹配除換行符(\n、\r)之外的任何單個或多個字符
# re.I	使匹配對大小寫不敏感
# re.L	做本地化識別(locale-aware)匹配
# re.M	多行匹配,影響 ^ 和 $
# re.S	使 . 匹配包括換行在內的所有字符
# re.U	根據Unicode字符集解析字符。這個標誌影響 \w, \W, \b, \B.
# re.X	該標誌通過給予你更靈活的格式以便你將正則表達式寫得更易於理解。

matchObj = re.match(r'(.*) is (.*?) .*', line, re.M | re.I)
# 用are 來分組,group(1) 爲左邊的 Cats ,group(2) 爲右邊的 smarter
if matchObj:
    print("matchObj.groups:", matchObj.groups())
    print("matchObj.group:", matchObj.group())
    print("matchObj.group(1):", matchObj.group(1))
    print("matchObj.group(2):", matchObj.group(2))
else:
    print("no match!")

# 搜索
print(re.search('www', 'www.baidu.com').span())
print(re.search('com', 'www.baidu.com').span())

line = "This is your life!"
searchObj = re.search(r'(.*) is (.*?) .*', line, re.M | re.I)

if searchObj:
    print("searchObj.group() : ", searchObj.group())
    print("searchObj.group(1) : ", searchObj.group(1))
    print("searchObj.group(2) : ", searchObj.group(2))
else:
    print("Nothing found!!")

line = "This is your life!"

matchObj = re.match(r'is', line, re.M | re.I)
if matchObj:
    print("match --> matchObj.group() : ", matchObj.group())
else:
    print("No match!!")

matchObj = re.search(r'is', line, re.M | re.I)
if matchObj:
    print("search --> matchObj.group() : ", matchObj.group())
    print("search --> matchObj.group() : ", matchObj.group()[0])  # 代表is中的i
    print("search --> matchObj.group() : ", matchObj.group()[1])  # 代表is中的s
else:
    print("No match!!")

phoneStr = "135-000-1234 # 電話號碼格式化!"
num = re.sub(r'#.*$', "", phoneStr)  # $匹配輸入字符串結尾的位置。
print("手機號碼:", num)

# 移除非數字的內容
num = re.sub(r'\D', "", phoneStr)  # \D 匹配一個非數字字符。等價於 [^0-9],不是0到9的數字。
print("電話號碼 : ", num)

pattern = re.compile(r'\d+')  # 用於匹配至少一個數字
m = pattern.match('abc12defghijk34lmno')  # 查找頭部,沒有匹配
print(m)

m = pattern.match('abc12defghijk34lmno', 2, 10)  # 從'e'的位置開始匹配,沒有匹配
print(m)

m = pattern.match('abc12defghijk34lmno', 3, 10)  # 從'1'的位置開始匹配,正好匹配
print(m)

print(m.group())  # 方法用於獲得一個或多個分組匹配的字符串,當要獲得整個匹配的子串時,可直接使用 group() 或 group(0);
print(m.start())  # 方法用於獲取分組匹配的子串在整個字符串中的起始位置(子串第一個字符的索引),參數默認值爲 0;
print(m.end())  # 方法用於獲取分組匹配的子串在整個字符串中的結束位置(子串最後一個字符的索引+1),參數默認值爲 0
print(m.span())  # 方法返回 (start(group), end(group))。

pattern = re.compile(r'\d+')  # 查找數字
result1 = pattern.findall('data 123 google 456')
result2 = pattern.findall('run88data123google456', 0, 10)

print(result1)
print(result2)

it = re.finditer(r"\d+","2112a322bc23j13f32") #在字符串中找到正則表達式所匹配的所有數字組,並把它們作爲一個迭代器返回。
for match in it:
    print (match.group() )

res=re.split('\W+', 'data, data, data.')
print(res)

res=re.split('(\W+)', ' data, data, data.')
print(res)

res=re.split('\W+', ' data, data, data.', 1)
print(res)

res=re.split('z*', 'z1z2z3zhello world')   # 對於一個找不到匹配的字符串而言,split 不會對其作出分割
print(res)
輸出結果:
(0, 3)
None
matchObj.groups: ('This', 'your')
matchObj.group: This is your life!
matchObj.group(1): This
matchObj.group(2): your
(0, 3)
(10, 13)
searchObj.group() :  This is your life!
searchObj.group(1) :  This
searchObj.group(2) :  your
No match!!
search --> matchObj.group() :  is
search --> matchObj.group() :  i
search --> matchObj.group() :  s
手機號碼: 135-000-1234 
電話號碼 :  1350001234
None
None
<_sre.SRE_Match object; span=(3, 5), match='12'>
12
3
5
(3, 5)
['123', '456']
['88', '1']
2112
322
23
13
32
['data', 'data', 'data', '']
['', ' ', 'data', ', ', 'data', ', ', 'data', '.', '']
['', 'data, data, data.']
['', '1', '2', '3', 'hello world']

對應的關鍵函數必須要通過案例才能更好的掌握它。

4、總結

在java裏面也支持正則表達式,是類似的,正則表達式可以更好的處理字符串操作。
對於正則表達式的語法規則有很多,可以記住一些常用的,其他的可以用到時再查。
一定要自己動手寫一寫Demo才能更好的去理解並應用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章