1. 程式人生 > >[Python模組]正則表示式 re模組的使用及例項

[Python模組]正則表示式 re模組的使用及例項

很喜歡Python教材中的這句格言: 有些人面臨問題時會想:“我知道, 我將使用正則表示式來解決這個問題.” 這讓他們面臨的問題變成了兩個. ---------Jamie Zawinski 正則表示式的確好用,但是複雜的模式難以閱讀和維護,與其把花在研究用正則表示式處理複雜的問題上,還不如把時間花在如何寫一套清晰,易維護的邏輯上(但是為什麼要用,還是因為爽啊) 關於正則表示式的語法,可以參閱我的這篇[學習筆記]正則表示式語法與使用速查

re模組

函式 描述
compile(pattern,[, flags]) 根據包含正則表示式的字串建立模式物件
search(pattern,string[, flags]) 在字串中查詢模式
sub(pat, repl, string[, count=0]) 對字串中域模式pat匹配的子串都替換為repl

函式re.compile()將字串表示的正則表示式轉換為模式物件,提高匹配效率,呼叫re.search()等函式時,如果使用的是字串表示的正則表示式,會在內部先轉換為模式物件再使用.如果轉為模式物件後,則後面每次使用正則表示式都無需進行轉換.即re.search(pat,string)等價於pat.search(string)

import re
line="http://www.python.org"
pat="(?<=\.).+(?=\.)"
#兩個.之間的內容 patobj=re.compile(pat) #建立模式物件 print(re.search(pat, line)) print(re.search(patobj, line)) #正則表示式與模式物件都能使用 print(patobj.search(line)) #輸出結果 <re.Match object; span=(11, 17), match='python'> <re.Match object; span=(11, 17), match='python'> <re.Match object; span=(11, 17), match=
'python'>

函式re.search在給定字串中查詢第一個與指定pat匹配的子串,如果找到將返回MatchObject(結果為True),否則為None.(結果為False) 觀察結果<re.Match object; span=(11, 17), match='python'>,發現MatchObject的匹配子串為'python',起始與終止位置為11,17

替換為java

line1 = re.sub(pat, "java", line) 
line2 = patobj.sub("java", line) 
print(line1)
print(line2)
#輸出結果
http://www.java.org
http://www.java.org
函式 描述
match(pattern, string,[, flags]) 在字串開頭匹配模式
split(pattern, string,[, maxsplit=0]) 根據模式來分割字串
findall(pattern, string) 返回一個列表,其中包含字串中所有與模式匹配的子串

函式re.match嘗試在給定字串開頭查詢與正則表示式匹配的子串,和re.search相似,如果找到這樣的子串,返回MatchObject,否則返回None 另外,re.match在模式與字串開頭匹配時就返回True,而不要求與整個字串匹配,如果要求完全匹配,需要在模式末尾加上$,從而將匹配檢查延伸到整個字串.

例如:找出以http協議開頭的網址

line1 = "http://www.python.org"
line2 = "ftp://192.168.1.1"
patobj = re.compile("http.*")
print(patobj.match(line1))
print(patobj.match(line2))
print(re.match("w{3}.*",line1)) #不是開頭匹配
#輸出結果
<re.Match object; span=(0, 21), match='http://www.python.org'>
None
None

函式re.split類似於字串方法str.split,但使用正則表示式來指定分隔符,而不是固定的分隔符

例如:分割字串中的網址

text="qq.com, baidu.com,,, python.org   csdn.net"
patobj=re.compile('[, ]+')
print(patobj.split(text))
print(patobj.split(text,1))#指定分割次數maxsplit
#輸出結果
['qq.com', 'baidu.com', 'python.org', 'csdn.net']
['qq.com', 'baidu.com,,, python.org   csdn.net']

函式re.findall返回一個列表,其中包含所有與給定模式匹配的子串```

例如:分割出java程式碼行中的所有的單詞以及逐個標點

text="public static void main(String[] args){ String str='...I'm fine.And you? --he said.';}"
print(re.findall('[\w]+',text))
print(re.findall('[\W]+',text))
#輸出結果
['public', 'static', 'void', 'main', 'String', 'args', 'String', 'str', 'I', 'm', 'fine', 'And', 'you', 'he', 'said']
[' ', ' ', ' ', '(', '[', ']', ' ', ')', '{', ' ', ' ', '=', "'", '.', '.', '.', "'", ' ', '.', ' ', '?', ' ', '-', '-', ' ', '.', "'", ';', '}']

匹配物件和編組

方法 描述
group([group1,…]) 獲取與給定子模式(編組)匹配的子串
start([group]) 返回與給定編組匹配的子串的起始位置
end([group]) 返回與給定編組匹配的子串的終止位置(與切片一樣,不包含終止位置)
span([group]) 返回與給定編組匹配的子串的起始和終止位置

在模組re中,查詢與模式匹配的子串的函式,在找到時返回MatchObject物件. 它包含了: 1.與模式匹配的子串的資訊 2.模式的哪部分與子串哪部分匹配的資訊.子串部分稱為編組 例如: 模式’(I am a (student)) who (live in (Guangzhou))’ 就包含了以下編組:

編組序號 子串
0(整個模式) I am a student who live in Guangzhou
1 I am a student
2 student
3 live in Guangzhou
4 Guangzhou

通過建立這樣模式,可以提取出感興趣,有不同意義的部分

text = "I am a student who live in Guangzhou"
pat = '(I am a (student)) who (live in (Guangzhou))'
for i in range(5):
   print(re.search(pat, text).group(i))
#輸出結果
I am a student who live in Guangzhou
I am a student
student
live in Guangzhou
Guangzhou

例如:提取網址中的不同部分

pat = re.compile('(^.*//)(.*)\.(.+)\.(.*?)/(.*)')
text = "http://www.abc.com/docs/index.html"
label = ["[Address]", "[Protocol]", "[Domain]", "[Main]", "[Suffix]", "[Doc]"]
for i in range(6):
    print(label[i], re.search(pat, text).group(i))
#輸出
[Address] http://www.abc.com/docs/index.html
[Protocol] http://
[Domain] www
[Main] abc
[Suffix] com
[Doc] docs/index.html
#
text = "https://docs.python.org/3/whatsnew/3.7.html" #更換地址
for i in range(6):
    print(label[i], re.search(pat, text).group(i))
#輸出
[Address] https://docs.python.org/3/whatsnew/3.7.html
[Protocol] https://
[Domain] docs
[Main] python
[Suffix] org
[Doc] 3/whatsnew/3.7.html

例項:模板應用

在已經標註好相應標籤的Java程式碼中,應用模板轉換為HTML程式碼,這裡以轉換註釋為例

labeled_code = \
    [
        ' [note=/* @author xxx]',
        ' [note=*  @since 1.1]   ',
        ' [note= */]',
        'public boolean isTranslate(int octal , int flags){',
        '[note=//...Some codes to realize]',
        'return true; ',
        '}'
    ]
note_pat = re.compile("\[note=(.+)]")  # 註釋模式
for text in labeled_code:
    note_match = note_pat.search(text)  # 返回MatchObject
    if note_match:
        note_text = note_match.group(0)
        note_repl = "<span class='note'> " + note_match.group(1) + " </span>"
        text = text.replace(note_text, note_repl) # 替換註釋
    print(text)

輸出結果:

 <span class='note'> /* @author xxx </span>
 <span class='note'> *  @since 1.1 </span>   
 <span class='note'>  */ </span>
public boolean isTranslate(int octal , int flags){
<span class='note'> //...Some codes to realize </span>
return true; 
}