1. 程式人生 > 實用技巧 >python正則表示式

python正則表示式

python正則表示式

1. 正則表示式基礎

1.1. 簡單介紹

正則表示式並不是Python的一部分。正則表示式是用於處理字串的強大工具,擁有自己獨特的語法以及一個獨立的處理引擎,效率上可能不如str自帶的方法,但功能十分強大。得益於這一點,在提供了正則表示式的語言裡,正則表示式的語法都是一樣的,區別只在於不同的程式語言實現支援的語法數量不同;但不用擔心,不被支援的語法通常是不常用的部分。如果已經在其他語言裡使用過正則表示式,只需要簡單看一看就可以上手了。

下圖展示了使用正則表示式進行匹配的流程:

正則表示式的大致匹配過程是:依次拿出表示式和文字中的字元比較,如果每一個字元都能匹配,則匹配成功;一旦有匹配不成功的字元則匹配失敗。如果表示式中有量詞或邊界,這個過程會稍微有一些不同,但也是很好理解的,看下圖中的示例以及自己多使用幾次就能明白。

下圖列出了Python支援的正則表示式元字元和語法:

1.2. 數量詞的貪婪模式與非貪婪模式

正則表示式通常用於在文字中查詢匹配的字串。Python裡數量詞預設是貪婪的(在少數語言裡也可能是預設非貪婪),總是嘗試匹配儘可能多的字元;非貪婪的則相反,總是嘗試匹配儘可能少的字元。例如:正則表示式"ab*"如果用於查詢"abbbc",將找到"abbb"。而如果使用非貪婪的數量詞"ab*?",將找到"a"。

1.3. 反斜槓的困擾

與大多數程式語言相同,正則表示式裡使用"\"作為轉義字元,這就可能造成反斜槓困擾。假如你需要匹配文字中的字元"\",那麼使用程式語言表示的正則表示式裡將需要4個反斜槓"\\\\":前兩個和後兩個分別用於在程式語言裡轉義成反斜槓,轉換成兩個反斜槓後再在正則表示式裡轉義成一個反斜槓。Python裡的原生字串很好地解決了這個問題,這個例子中的正則表示式可以使用r"\\"表示。同樣,匹配一個數字的"\\d"可以寫成r"\d"。有了原生字串,你再也不用擔心是不是漏寫了反斜槓,寫出來的表示式也更直觀。

1.4. 匹配模式

正則表示式提供了一些可用的匹配模式,比如忽略大小寫、多行匹配等,這部分內容將在Pattern類的工廠方法re.compile(pattern[, flags])中一起介紹。

2. re模組

2.1. 開始使用re

Python通過re模組提供對正則表示式的支援。使用re的一般步驟是先將正則表示式的字串形式編譯為Pattern例項,然後使用Pattern例項處理文字並獲得匹配結果(一個Match例項),最後使用Match例項獲得資訊,進行其他的操作。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # encoding: UTF-8
importre # 將正則表示式編譯成Pattern物件 pattern=re.compile(r'hello') # 使用Pattern匹配文字,獲得匹配結果,無法匹配時將返回None match=pattern.match('hello world!') ifmatch: # 使用Match獲得分組資訊 printmatch.group() ### 輸出 ### # hello

re.compile(strPattern[, flag]):

這個方法是Pattern類的工廠方法,用於將字串形式的正則表示式編譯為Pattern物件。 第二個引數flag是匹配模式,取值可以使用按位或運算子'|'表示同時生效,比如re.I | re.M。另外,你也可以在regex字串中指定模式,比如re.compile('pattern', re.I | re.M)與re.compile('(?im)pattern')是等價的。
可選值有:

    • re.I(re.IGNORECASE): 忽略大小寫(括號內是完整寫法,下同)
    • M(MULTILINE): 多行模式,改變'^'和'$'的行為(參見上圖)
    • S(DOTALL): 點任意匹配模式,改變'.'的行為
    • L(LOCALE): 使預定字元類 \w \W \b \B \s \S 取決於當前區域設定
    • U(UNICODE): 使預定字元類 \w \W \b \B \s \S \d \D 取決於unicode定義的字元屬性
    • X(VERBOSE): 詳細模式。這個模式下正則表示式可以是多行,忽略空白字元,並可以加入註釋。以下兩個正則表示式是等價的:

Match

Match物件是一次匹配的結果,包含了很多關於此次匹配的資訊,可以使用Match提供的可讀屬性或方法來獲取這些資訊。

屬性:

  1. string: 匹配時使用的文字。
  2. re: 匹配時使用的Pattern物件。
  3. pos: 文字中正則表示式開始搜尋的索引。值與Pattern.match()和Pattern.seach()方法的同名引數相同。
  4. endpos: 文字中正則表示式結束搜尋的索引。值與Pattern.match()和Pattern.seach()方法的同名引數相同。
  5. lastindex: 最後一個被捕獲的分組在文字中的索引。如果沒有被捕獲的分組,將為None。
  6. lastgroup: 最後一個被捕獲的分組的別名。如果這個分組沒有別名或者沒有被捕獲的分組,將為None。

方法:

    1. group([group1, …]):
      獲得一個或多個分組截獲的字串;指定多個引數時將以元組形式返回。group1可以使用編號也可以使用別名;編號0代表整個匹配的子串;不填寫引數時,返回group(0);沒有截獲字串的組返回None;截獲了多次的組返回最後一次截獲的子串。
    2. groups([default]):
      以元組形式返回全部分組截獲的字串。相當於呼叫group(1,2,…last)。default表示沒有截獲字串的組以這個值替代,預設為None。
    3. groupdict([default]):
      返回以有別名的組的別名為鍵、以該組截獲的子串為值的字典,沒有別名的組不包含在內。default含義同上。
    4. start([group]):
      返回指定的組截獲的子串在string中的起始索引(子串第一個字元的索引)。group預設值為0。
    5. end([group]):
      返回指定的組截獲的子串在string中的結束索引(子串最後一個字元的索引+1)。group預設值為0。
    6. span([group]):
      返回(start(group), end(group))。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 # match,從起始位置開始匹配,匹配成功返回一個物件,未匹配成功返回None match(pattern, string, flags=0) # pattern: 正則模型 # string : 要匹配的字串 # falgs : 匹配模式 X VERBOSE Ignore whitespaceandcommentsfornicer looking RE's. I IGNORECASE Perform case-insensitive matching. M MULTILINE"^"matches the beginning of lines (after a newline) as well as the string. "$"matches the end of lines (before a newline) as well as the end of the string. S DOTALL"."matchesanycharacter atall, including the newline. A ASCII For string patterns, make \w, \W, \b, \B, \d, \D match the corresponding ASCII character categories (rather than the wholeUnicodecategories, whichisthe default). For bytes patterns, this flagisthe only available behaviourandneedn't be specified. L LOCALE Make \w, \W, \b, \B, dependent on the current locale. UUNICODEFor compatibility only. Ignoredforstring patterns (it isthe default),andforbiddenforbytes patterns.
demo

search(string[, pos[, endpos]]) | re.search(pattern, string[, flags]):
這個方法用於查詢字串中可以匹配成功的子串。從string的pos下標處起嘗試匹配pattern,如果pattern結束時仍可匹配,則返回一個Match物件;若無法匹配,則將pos加1後重新嘗試匹配;直到pos=endpos時仍無法匹配則返回None。
pos和endpos的預設值分別為0和len(string));re.search()無法指定這兩個引數,引數flags用於編譯pattern時指定匹配模式。

1 2 # search,瀏覽整個字串去匹配第一個,未匹配成功返回None # search(pattern, string, flags=0)
demo

split(string[, maxsplit]) | re.split(pattern, string[, maxsplit]):
按照能夠匹配的子串將string分割後返回列表。maxsplit用於指定最大分割次數,不指定將全部分割。

1 2 3 4 5 6 7 # split,根據正則匹配分割字串 split(pattern, string, maxsplit=0, flags=0) # pattern: 正則模型 # string : 要匹配的字串 # maxsplit:指定分割個數 # flags : 匹配模式
demo

findall(string[, pos[, endpos]]) | re.findall(pattern, string[, flags]):
搜尋string,以列表形式返回全部能匹配的子串。

1 2 3 # findall,獲取非重複的匹配列表;如果有一個組則以列表形式返回,且每一個匹配均是字串;如果模型中有多個組,則以列表形式返回,且每一個匹配均是元祖; # 空的匹配也會包含在結果中 #findall(pattern, string, flags=0)
demo

sub(repl, string[, count]) | re.sub(pattern, repl, string[, count]):
使用repl替換string中每一個匹配的子串後返回替換後的字串。
當repl是一個字串時,可以使用\id或\g<id>、\g<name>引用分組,但不能使用編號0。
當repl是一個方法時,這個方法應當只接受一個引數(Match物件),並返回一個字串用於替換(返回的字串中不能再引用分組)。
count用於指定最多替換次數,不指定時全部替換。

1 2 3 4 5 6 7 8 # sub,替換匹配成功的指定位置字串 sub(pattern, repl, string, count=0, flags=0) # pattern: 正則模型 # repl : 要替換的字串或可執行物件 # string : 要匹配的字串 # count : 指定匹配個數 # flags : 匹配模式  
demo

subn(repl, string[, count]) |re.sub(pattern, repl, string[, count]):
返回 (sub(repl, string[, count]), 替換次數)。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 importre p=re.compile(r'(\w+) (\w+)') s='i say, hello world!' printp.subn(r'\2 \1', s) deffunc(m): returnm.group(1).title()+' '+m.group(2).title() printp.subn(func, s) ### output ### # ('say i, world hello!', 2) # ('I Say, Hello World!', 2)