[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;
}