Python Library: re
正則表達式是處理字符串最重要的一種手段了。python
1. 基本信息正則表達式
特殊字符(需轉義處理):
. ^ $ * + ? { } [ ] \ | ( )函數
字符定義:
• \d: 十進制數字,至關於 [0-9]
• \D: 非數字字符,至關於 [^0-9]
• \s: 空白字符,至關於 [ \t\n\r\f\v]。
• \S: 非空白字符。
• \w: 字母或數字,至關於 [a-zA-Z0-9]。
• \W: 非字母數字。
• .: 任意字符。
• |: 或。
• ^: 非或開始位置。
• $: 結束位置。
• \b: 單詞邊界(完整單詞,而非其餘單詞中的子串)。
• \B: 非單詞邊界。
重複:
• *: 0 或 任意個字符。
• ?: 0 或 一個字符。
• +: 1 或 多個字符。
• {n, m}: n 到 m 個字符。
• {n}: n 個字符。
• {n,}: n 到儘量多的字符。
• {,m}: 至關於 {0,m}。
一般使用添加一個 "?" 來避免貪婪匹配。spa
re 有幾個重要的函數:
• match(): 匹配字符串開始位置。
• search(): 掃描字符串,找到第一個位置。
• findall(): 找到所有匹配,以列表返回。
• finditer(): 找到所有匹配,以迭代器返回。
match 和 search 僅匹配一次,匹配不到返回 None。code
python hljs 19行對象
>>> import re >>> s = "12abc345ab" >>> m = re.match(r"\d+", s) >>> m.group(), m.span() ('12', (0, 2)) >>> m = re.match(r"\d{3,}", s) >>> m is None True >>> m = re.search(r"\d{3,}", s) >>> m.group(), m.span() ('345', (5, 8)) >>> m = re.search(r"\d+", s) >>> m.group(), m.span() ('12', (0, 2))
findall 返回列表(或空列表),finditer 和 match/search 同樣返回 MatchObject 對象。文檔
python hljs 17行字符串
>>> ms = re.findall(r"\d+", s) >>> ms ['12', '345'] >>> ms = re.findall(r"\d{5}", s) >>> ms [] >>> for m in re.finditer(r"\d+", s): print m.group(), m.span() ... 12 (0, 2) 345 (5, 8) >>> for m in re.finditer(r"\d{5}", s): print m.group(), m.span() ... >>>
match、search、finditer 返回的對象 —— MatchObject。
• group(): 返回匹配的完整字符串。
• start(): 匹配的開始位置。
• end(): 匹配的結束位置。
• span(): 包含起始、結束位置的元組。
• groups(): 返回分組信息。
• groupdict(): 返回命名分組信息。it
python hljs 20行編譯
>>> >>> m = re.match(r"(\d+)(?P<letter>[abc]+)", s) >>> m.group() '12abc' >>> m.start() 0 >>> m.end() 5 >>> m.span() (0, 5) >>> m.groups() ('12', 'abc') >>> m.groupdict() {'letter': 'abc'}
group() 能夠接收多個參數,用於返回指定序號的分組。
python hljs 35行
>>> m.group(0) '12abc' >>> m.group(1) '12' >>> m.group(2) 'abc' >>> m.group(1,2) ('12', 'abc') >>> m.group(0,1,2) ('12abc', '12', 'abc') start()、end() 和 span() 一樣能接收分組序號。和 group() 同樣,序號 0 表示總體匹配結果。 >>> m.start(0), m.end(0) (0, 5) >>> m.start(1), m.end(1) (0, 2) >>> m.start(2), m.end(2) (2, 5) >>> m.span(0) (0, 5) >>> m.span(1) (0, 2) >>> m.span(2) (2, 5)
編譯標誌
能夠用 re.I、re.M 等參數,也能夠直接在表達式中添加 "(?iLmsux)" 標誌。
• s: 單行。"." 匹配包括還行符在內的全部字符。
• i: 忽略大小寫。
• L: 讓 "\w" 能匹配當地字符,貌似對中文支持很差。
• m: 多行。
• x: 忽略多餘的空白字符,讓表達式更易閱讀。
• u: Unicode。
試試看。
python hljs 9行
>>> re.findall(r"[a-z]+", "%123Abc%45xyz&") ['bc', 'xyz'] >>> re.findall(r"[a-z]+", "%123Abc%45xyz&", re.I) ['Abc', 'xyz'] >>> re.findall(r"(?i)[a-z]+", "%123Abc%45xyz&") ['Abc', 'xyz']
下面這麼寫好看多了吧?
python hljs 8行
>>> patter = r""" ... (\d+) #number ... ([a-z]+) #letter ... """ >>> re.findall(pattern, "%123Abc\n%45xyz&", re.I | re.S | re.X) [('123', 'Abc'), ('45', 'xyz')]
(1) 命名組:(?P...)
python hljs 6行
>>> for m in re.finditer(r"(?P<number>\d+)(?P<letter>[a-z]+)", "%123Abc%45xyz&", re.I): ... print m.groupdict() ... {'number': '123', 'letter': 'Abc'} {'number': '45', 'letter': 'xyz'}
(2) 無捕獲組:(?:...)
做爲匹配條件,但不返回。
python hljs 6行
>>> for m in re.finditer(r"(?:\d+)([a-z]+)", "%123Abc%45xyz&", re.I): ... print m.groups() ... ('Abc',) ('xyz',)
(3) 反向引用:<number> 或 (?P=name)
引用前面的組。
python hljs 17行
>>> for m in re.finditer(r"<a>\w+</a>", "%<a>123Abc</a>%<b>45xyz</b>&"): ... print m.group() ... <a>123Abc</a> >>> for m in re.finditer(r"<(\w)>\w+</(\1)>", "%<a>123Abc</a>%<b>45xyz</b>&"): ... print m.group() ... <a>123Abc</a> <b>45xyz</b> >>> for m in re.finditer(r"<(?P<tag>\w)>\w+</(?P=tag)>", "%<a>123Abc</a>%<b>45xyz</b>&"): ... print m.group() ... <a>123Abc</a> <b>45xyz</b>
(4) 聲明
正聲明 (?=...):組內容必須出如今右側,不返回。
負聲明 (?!...):組內容不能出如今右側,不返回。
反向正聲明 (?<=):組內容必須出如今左側,不返回。
反向負聲明 (?<!):組內容不能出如今左側,不返回。
python hljs 11行
>>> for m in re.finditer(r"\d+(?=[ab])", "%123Abc%45xyz%780b&", re.I): ... print m.group() ... 123 780 >>> for m in re.finditer(r"(?<!\d)[a-z]{3,}", "%123Abc%45xyz%byse&", re.I): ... print m.group() ... byse
更多信息請閱讀官方文檔或更專業的書籍。
(1) split: 用 pattern 作分隔符切割字符串。若是用 "(pattern)",那麼分隔符也會返回。
python hljs 6行
>>> re.split(r"\W", "abc,123,x") ['abc', '123', 'x'] >>> re.split(r"(\W)", "abc,123,x") ['abc', ',', '123', ',', 'x']
(2) sub: 替換子串。
可指定替換次數。
python hljs 6行
>>> re.sub(r"[a-z]+", "*", "abc,123,x") '*,123,*' >>> re.sub(r"[a-z]+", "*", "abc,123,x", 1) '*,123,x'
subn() 和 sub() 差很少,不過返回 "(新字符串,替換次數)"。
python hljs 3行
>>> re.subn(r"[a-z]+", "*", "abc,123,x") ('*,123,*', 2)
還能夠將替換字符串改爲函數,以便替換成不一樣的結果。
python hljs 10行
>>> def repl(m): ... print m.group() ... return "*" * len(m.group()) ... >>> re.subn(r"[a-z]+", repl, "abc,123,x") abc x ('***,123,*', 2)