模式匹配與正規表示式

xie仗劍天涯發表於2017-08-03

# 不用正規表示式來查詢文字模式(匹配一個電話號碼,格式為:415-555-4242)
def phone_num(text):
    if len(text) != 12:
        return  False
    for i in range(0,3):
        if not text[i].isdecimal():
            return False
    if text[3] != "-":
        return False
    for i in range(4,7):
        if not text[i].isdecimal():
            return False
    if text[7] != "-":
        return False
    for i in range(8,12):
        if not text[i].isdecimal():
            return False
    return True

if __name__ == "__main__":
    message = input(">>>:")
    for i in range(len(message)):
        chunk = message[i:i+12]
        if phone_num(chunk):
            print ("\033[31;1mphone num\033[0m:%s"%chunk)
# >>>: Call me at 415-555-1011 tomorrow. 415-555-9999 is my office
# phone num:415-555-1011
# phone num:415-555-9999

  

# 用正規表示式查詢文字模式
import re
phone_num_re = re.compile(r"\d\d\d-\d\d\d\-\d\d\d\d")
number = input(">>>:")
chunk_re = phone_num_re.search(number)
print ("\033[31;1mphone_num_re\033[0m:%s"%chunk_re.group())
# >>>: Call me at 415-555-1011 tomorrow
# phone_num_re:415-555-1011
chunk_re_find = phone_num_re.findall(number)
print ("\033[31;1mphone_num_re\033[0m:%s"%chunk_re_find)
# >>>:Call me at 415-555-1011 tomorrow. 415-555-9999 is my office
# phone_num_re:['415-555-1011', '415-555-9999']

  

# 用管道匹配多個分組
"""
字元|稱為“管道”。希望匹配許多表示式中的一個時,就可以使用它
利用findall()方法,可以找到“所有”匹配的地方
"""
import re
heroRegex = re.compile(r"linux|python")
mo1 = heroRegex.search("linux and python is my love")
print (mo1.group())
# linux
mo2 = heroRegex.findall("linux and python is my love")
print (mo2)
# ['linux', 'python']

  

# 用問號實現可選匹配
# 字元?表明它前面的分組在這個模式中是可選的
batRefex = re.compile(r"Bat(wo)?man")
mo3 = batRefex.search("The Adventures of Batman")
print (mo3.group())


# 用星號匹配零次或多次
batRegex1 = re.compile(r'Bat(wo)*man')
mo5 = batRegex1.search('The Adventures of Batwoman')
mo4 = batRegex1.search('The Adventures of Batwowowowoman')
print (mo5.group())
print (mo4.group())

# 用加號匹配一次或多次
# *意味著“匹配零次或多次”,+(加號)則意味著“匹配一次或多次”。星號不要求分組出現在匹配的字串中,但加號不同,加號前面的分組必須“至少出現一次”
batRegex2 = re.compile(r'Bat(wo)+man')
mo6 = batRegex2.search('The Adventures of Batwoman')
print (mo6.group())
mo7 = batRegex2.search('The Adventures of Batwowowowoman')
print (mo7.group())
# Batwoman
# Batwowowowoman

  

# 用花括號匹配特定次數



"""
findall()方法

search()將返回一個Match物件,包含被查詢字串中的“第一次”匹配的文字,而findall()方法將返回一組字串,包含被查詢字串中的所有匹配。
"""

# 通配字元
# .(句點)字元稱為“萬用字元”。它匹配除了換行之外的所有字元,句點字元只匹配一個字元.
# 要匹配真正的句點,就是用倒斜槓轉義:\.
atRegex = re.compile(r'.at')
print (atRegex.findall('The cat in the hat sat on the flat mat.'))
# ['cat', 'hat', 'sat', 'lat', 'mat']


# 用點-星匹配所有字元
nameRegex = re.compile(r'First Name: (.*) Last Name: (.*)')
mm = nameRegex.search('First Name: Al Last Name: Sweigart')
print (mm.group(1))
print (mm.group(2))
# Al
# Sweigart


# 用句點字元匹配換行
# 通過傳入re.DOTALL 作為re.compile()的第二個引數,可以讓句點字元匹配所有字元,包括換行字元
noNewlineRegex = re.compile('.*') # 不能匹配換行
mm2 = noNewlineRegex.search('Serve the public trust.\nProtect the innocent.\nUphold the law.').group()
print (mm2)
# Serve the public trust.
newlineRegex1 = re.compile('.*', re.DOTALL)
mm3 = newlineRegex1.search('Serve the public trust.\nProtect the innocent.\nUphold the law.').group()
print (mm3)
# Serve the public trust.
# Protect the innocent.
# Uphold the law.


# 不區分大小寫的匹配
# 讓正規表示式不區分大小寫,可以向re.compile()傳入re.IGNORECASE 或re.I,作為第二個引數
robocop = re.compile(r'robocop', re.I)
ro = robocop.search('RoboCop is part man, part machine, all cop.').group()
print (ro)
# RoboCop


# 用sub()方法替換字串
# Regex物件的sub()方法需要傳入兩個引數。第一個引數是一個字串,用於取代發現的匹配。第二個引數是一個字串,即正規表示式。sub()方法返回替換完成後的字串
namesRegex = re.compile(r'Agent \w+')
resub = namesRegex.sub('CENSORED', 'Agent Alice gave the secret documents to Agent Bob.')
print (resub)
# CENSORED gave the secret documents to CENSORED.


# 管理複雜的正規表示式
# 忽略正規表示式字串中的空白符和註釋,可以向re.compile()傳入變數re.VERBOSE,作為第二個引數。
# 使用了三重引號('"),建立了一個多行字串。這樣就可以將正規表示式定義放在多行中,讓它更可讀
# 示例:
phoneRegex = re.compile(r'''(
(\d{3}|\(\d{3}\))?  # area code
(\s|-|\.)?           # separator
\d{3}                # first 3 digits
(\s|-|\.)           # separator
\d{4}                # last 4 digits
(\s*(ext|x|ext.)\s*\d{2,5})? # extension
)''', re.VERBOSE)


# 組合使用re.IGNOREC ASE、re.DOTALL 和re.VERBOSE
# 可以使用管道字元(|)將變數組合起來




"""
專案:電話號碼和E-mail 地址提取程式

# 為電話號碼建立一個正規表示式
PhoneRegex = re.compile(r"(\d{3}|\(\d{3}\))?(\s|-|\.)?(\d{3})(\s|-|\.)(\d{4})(\s*(ext|x|ext.)\s*(\d{2,5}))?")

# 為E-mail 地址建立一個正規表示式
MailRegex = re.compile(r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}")

  

 

參考資料:Python程式設計快速上手讓繁瑣工作自動化

 

相關文章