摘要:正則表達式匹配的字符串限定范圍和否定除了單字符外,字符集還支持匹配指定的字符范圍。問號要求正則表達式引擎在當前正則表達式中盡可能少地匹配字符。正則表達式匹配的字符串表示簡單浮點數的字符串擴展表示法正則表達式的擴展表示法,以問號開始。
簡介
正則表達式 是包含文本和特殊字符的字符串, 為高級的文本模式匹配, 抽取, 與文本形式的搜索和替換功能提供了基礎
Python通過標準庫re模塊來支持正則表達式
模式匹配的兩種方法完成匹配(模式匹配)
搜索(search())
匹配(match())
特殊符號和字符元字符指正則表達式中的特殊符號和字符。
符號符號 | 描述 | 示例 | |||
---|---|---|---|---|---|
literal | 匹配文本字符串的字面值literal | foo | |||
`re1 | re2` | 匹配正則表達式re1和re2 | `foo | bar` | |
. | 匹配任何字符(除 之外) | f.o | |||
^ | 匹配字符串起始部分 | ^foo | |||
$ | 匹配字符串終止部分 | bar$ | |||
* | 匹配0次或者多次前面出現的正則表達式 | [A-Za-z0-9]* | |||
+ | 匹配1次或者多次前面出現的正則表達式 | [a-z]+.com | |||
? | 匹配0次或者1次前面出現的正則表達式 | goo? | |||
{N} | 匹配N次前面出現的正則表達式 | [0-9]{3} | |||
{M,N} | 匹配M~N次前面出現的正則表達式 | [0-9]{5,9} | |||
[…] | 匹配來自字符集的任意單一字符 | [aeiou] | |||
[x-y] | 匹配x~y范圍中的任意單一字符 | [0-9], [A-Za-z] | |||
[^…] | 不匹配此字符集中出現的任何一個字符, 包括某一范圍的字符 | [^aeiou], [^A-Za-z] | |||
`(* | + | ? | {})?` | 用于匹配上面頻繁出現/重復出現符號的非貪婪版本(*、+、?、{}) | .*?[a-z] |
(…) | 匹配封閉的正則表達式,然后另存為子組 | `([0-9]{3})?,f(oo | u)bar` |
符號 | 描述 | 示例 |
---|---|---|
d | 匹配任何十進制數字,與[0-9]一致 | datad+.txt |
D | 與d相反 | |
w | 匹配任何字母數字字符,與[A-Za-z0-9]相同 | |
W | 與w相反 | |
s | 匹配任何空格字符,與[ vf]相同 | |
S | 與s相反 | |
N | 匹配已保存的子組 N | price:1 |
c | 逐字匹配任何特殊字符c | .,,* |
A | 匹配字符串起始,與^相同 | |
匹配字符串結束,與$相同 |
符號 | 描述 | 示例 | |||
---|---|---|---|---|---|
(?iLmsux) | 在正則表達式本身中嵌入一個或多個特殊特殊標記 (vs. via function/method) | (?x),(?im) | |||
(?:...) | 匹配一個不用保存的分組 | (?:w+.) | |||
(?P |
使用名字表示的正則分組 | (?P) | |||
(?#...) | 表示注釋,所有內容會被忽略 | (?#comment) | |||
(?=...) | 匹配條件是如果...出現在之后的位置,而不使用輸入字符串;稱作正向前視斷言(positive lookahead assertion) | (?=.com) | |||
(?!...) | 匹配條件是如果...不出現在之后的位置,而不使用輸入字符串;稱作負向前視斷言(negative lookahead assertion) | (?!.net) | |||
(?<=...) | 匹配條件是如果...出現在之前的位置,而不使用輸入字符串;稱作正向后視斷言(positive lookbehind assertion) | (?<=800-) | |||
(? | 匹配條件是如果...不出現在之前的位置,而不使用輸入字符串;稱作負向后視斷言(negative lookbehind assertion) | (? | |||
`(?(id/name)Y | N)` | Conditional match of regex Y if group with given id or name exists else N; | N is optional | `(?(1)y | x)` |
管道符號在正則表達式中又稱為擇一匹配符,表示 從多個模式中選擇其一 的操作。
正則表達式 | 匹配的字符串 | ||
---|---|---|---|
`at | home` | at,home | |
`r2d2 | c3po` | r2d2,c3po | |
`bat | bet | bit` | bat,bet,bit |
句點(.)符號匹配除了換行符 以外的任何字符。無論字母、數字、空格(不包括 換行符)、可打印字符、不可打印字符,使用.都可以匹配。
正則表達式 | 匹配的字符串 |
---|---|
f.0 | 匹配在字母f和o之間的任意一個字符,如:fao,f9o,f#o等 |
.. | 任意兩個字符 |
.end | 匹配在字符串end之前的任意一個字符 |
注意
要顯式匹配一個句點符號本身,必須使用反斜線轉義句點符號的功能,例如.。
匹配起始或結尾有些符號和相關的特殊字符用于在字符串的起始或結尾部分指定用于搜索的模式。
符號 | 位置 |
---|---|
^ 或 A | 起始 |
$ 或 | 結尾 |
簡單示例如下。
正則表達式 | 匹配的字符串 |
---|---|
^Froms | 任何以From作為開頭的字符串 |
/bin/bash$ | 任何以/bin/bash結尾的字符串 |
^Subject:hi$ | 匹配Subject:hi |
符號 | 說明 |
---|---|
匹配一個單詞的邊界 | |
B | 匹配不是一個單詞的邊界 |
簡單示例如下。
正則表達式 | 匹配的字符串 |
---|---|
the | 任何包含the的字符串 |
the | 任何以the開始的字符串 |
the | 僅僅匹配單詞the |
Bthe | 任何包含但并不以the作為起始的字符串 |
使用[]創建字符集,可以匹配某些特定字符。
正則表達式 | 匹配的字符串 |
---|---|
b[aeiu]t | bat,bet,bit,but |
[cr][23] | c2,c3,r2,r3 |
除了單字符外,字符集還支持匹配指定的字符范圍。兩個字符中間用連字符-連接,用于指定一個字符的范圍。如果^緊跟在左括號后面,這個符號就表示不匹配給定字符集中任何一個字符。
正則表達式 | 匹配的字符串 |
---|---|
z.[0-9] | z 后面跟著任何一個字符,然后跟著一個數字 |
[r-u][env-y][us] | 等價于[rstu][envwxy][us] ,比如匹配res |
[^aeiou] | 匹配一個非元音字符 |
[^ ] | 不匹配制表符或換行符 |
符號 | 說明 |
---|---|
* | 匹配左側的正則表達式出現零次或多次的情形,這稱作Kleene閉包 |
+ | 匹配一次或多次出現的正則表達式,這稱作正閉包操作符 |
? | 操作符將匹配零次或者一次出現的正則表達式 |
{} | 里面或者是單值,或者是一對由逗號分隔的數值;{N}表示匹配N次;{N,M}表示匹配N~M次 |
如果問號緊跟在任何使用閉包操作符的匹配后面,它將直接要求正則表達式引擎匹配盡可能少的次數。當模式匹配使用分組操作符時,正則表達式引擎將試圖吸收匹配該模式的盡可能多的字符,這通常叫做貪婪匹配。問號要求正則表達式引擎在當前正則表達式中盡可能少地匹配字符。
簡單示例。
正則表達式 | 匹配的字符串 |
---|---|
[dn]ot | do,dot,no,not |
0?[1-9] | 可能存在前置0的數字 |
[0-9]{15,16} | 匹配15或者16個數字 |
?[^>]+> | 匹配HTML標簽 |
有一些特殊字符能夠表示字符集。
符號 | 描述 | |
---|---|---|
d | 匹配任何十進制數字,與[0-9]一致 | datad+.txt |
D | 與d相反 | |
w | 匹配任何字母數字字符,與[A-Za-z0-9]相同 | |
W | 與w相反 | |
s | 匹配任何空格字符,與[ vf]相同 | |
S | 與s相反 |
簡單示例。
正則表達式 | 匹配的字符串 |
---|---|
w+-d+ | 一個由字母數字組成的字符串和一串由一個連字符分割的數字 |
有時候不僅想要知道整個字符串是否匹配我們的標準,而且想要知道能否提取任何已經成功匹配的特定字符串或者子字符串,可以使用分組來實現。
一對圓括號可以實現一下任意一個功能:
對正則表達式進行分組
匹配子組
對正則表達式分組,可以在整個正則表達式中使用重復的操作符。
使用圓括號進行分組的一個副作用就是,匹配模式的子字符串可以保存起來供后續使用。這些子組能夠被同一次的匹配或者搜索重復調用,或者提取出來用于后續處理。
匹配子組的重要性在于,很多時候除了進行匹配操作以外,我們還想要提取所匹配的模式。
簡單示例如下。
正則表達式 | 匹配的字符串 |
---|---|
d+(.d*)? | 表示簡單浮點數的字符串 |
正則表達式的擴展表示法,以問號開始(?...)。他們通常用于在判斷匹配之前提供標記,實現一個前視或者后視匹配,或者條件檢查。
盡管這些符號使用圓括號,但是只有(?P
正則表達式 | 匹配的字符串 | |
---|---|---|
(?:w+.)* | 以句點作為結尾的字符串,例如 google.,但是這些匹配不會保存下來供后續使用和數據檢索 | |
(?#comment) | 注釋 | |
(?=.com) | 如果一個字符串和后面跟著 .com 才做匹配操作,并不使用任何目標字符串 | |
(?!.net) | 如果一個字符串后面不是跟著.net才做匹配操作 | |
(?<=800-) | 如果字符串之前為800-才做匹配 | |
(? | 如果一個字符串之前不是192.168.才做匹配操作 | |
`(?(1)y | x)` | 如果一個匹配組1(1)存在,就與y匹配;否則與x匹配 |
在Python中,re模塊支持更強大而且更通用的Perl風格的正則表達式,該模塊允許多個線程共享同一個已編譯的正則表達式對象,也支持命名子組。
re模塊 re模塊函數函數 | 描述 |
---|---|
compile(pattern, flags=0) | 使用任何可選的標記來編譯正則表達式的模式,然后返回一個正則表達式對象 |
函數 | 描述 | 返回值 |
---|---|---|
match(pattern, string, flags=0) | 使用帶有可選標記的正則表達式模式匹配字符串 | 匹配成功,返回匹配對象;如果失敗,返回None |
search(pattern, string, flags=0) | 使用可選標記搜索字符串中第一次出現的正則表達式模式 | 匹配成功,返回匹配對象;如果失敗,返回None |
findall(pattern, string[, flags]) | 查找字符串中所有(非重復)出現的正則表達式模式 | 匹配列表 |
finditer(pattern, string[, flags]) | 與findall相同,但返回的不是列表 | 一個迭代器 |
split(pattern, string,max=0 ) | 根據正則表達式的模式分隔符,split函數將字符串分割為列表,然后返回成功匹配的列表,分割最多操作max次,默認分割所有匹配成功的位置 | 分割后的列表 |
sub(pattern, repl, string, count=0) | 使用repl替換count次正則表達式的模式在字符串中出現的位置;默認替換所有 | 替換操作數目 |
purge() | 清除隱式編譯的正則表達式模式;清除緩存 |
函數 | 描述 |
---|---|
group(num=0) | 返回整個匹配對象;或者編號為num的特定子組 |
groups(default=None) | 返回一個包含所有匹配子組的元組(如果沒有成功匹配,則返回一個空元組) |
groupdict(default=None) | 返回一個包含所有匹配的命名子組的字典,所有的子組名稱作為字典的鍵(如果沒有匹配成功返回一個空元組) |
屬性 | 描述 |
---|---|
re.I,re.IGNORECASE | 不區分大小寫的匹配 |
re.L,re.LOCALE | 根據所使用的本地語言環境通過w,W,,B,s,S實現匹配 |
re.M,re.MULTILINE | ^和$分別匹配目標字符串中行的起始和結尾,而不是嚴格匹配整個字符串本身的起始和結尾 |
re.S,re.DOTALL | . 通常匹配除了 之外的所有單個字符,該標記可以使.匹配換行符 |
re.X, re.VERBOSE | 通過反斜線轉義,否則所有空格加上#都被忽略 |
在Python中可以通過兩種途徑使用正則表達式:
re模塊函數
調用編譯后的正則表達式對象方法
在Python中由兩類對象和正則表達式有關:
re.compile生成的表達式對象
匹配對象(成功調用 match() 或 search() 之后返回的對象)
幾乎所有的re模塊函數都可以作為regex對象的方法。
可以通過按位或操作符(|)合并使用多個標記
可以使用(?FLAG)將標記嵌入到正則表達式
>>> re.match(r"(?i)the", "the") <_sre.SRE_Match object; span=(0, 3), match="the"> >>> re.match(r"(?i)the", "The") <_sre.SRE_Match object; span=(0, 3), match="The"> >>> re.match(r"the", "The") >>>匹配對象以及group()和groups()方法
匹配對象是成功調用match()或者search()返回的對象。匹配對象有兩個主要的方法: group()和groups()。
group()要么返回整個匹配對象,要么根據要求返回特定子組。groups()則僅返回一個包含唯一或者全部子組的元組。如果沒有子組的要求,那么當group()仍返回整個匹配時,groups()返回一個空元組。
Python正則表達式允許命名匹配。
使用match方法匹配字符串match方法試圖從字符串的起始部分對模式進行匹配。
如果匹配成功,就返回一個匹配對象;如果匹配對象失敗,就返回None。
匹配對象的group()方法能夠用于顯示那個成功的匹配。
Python 3.5.4rc1 (default, Jul 25 2017, 08:53:34) [GCC 6.4.0 20170704] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import re >>> m = re.match("foo", "foo") >>> if m is not None: ... m.group() ... "foo" >>> m <_sre.SRE_Match object; span=(0, 3), match="foo">
只要模式從字符串的起始部分匹配,即使字符串比模式長,匹配也仍然能夠成功。匹配結果是從較長字符串中抽取的匹配部分。
>>> re.match("foo", "food on the table").group() "foo"使用search在字符串中查找模式
search函數在任意位置對給定正則表達式模式搜索第一次出現的匹配情況。如果搜索到成功的匹配,就會返回一個匹配對象;否則,返回None。
與match相比,match只能從起始開始匹配,search可以匹配任意位置。
>>> m = re.match("foo", "seafood") >>> m.group() if m is not None else print(m) None >>> m = re.search("foo", "seafood") >>> m.group() if m is not None else print(m) "foo"
上面代碼,使用match匹配失敗,使用search則匹配成功。
匹配多個字符串管道符號或擇一匹配符號(|)的使用。
>>> bt = "bat|bet|bit" >>> m = re.match(bt, "bat") >>> m.group() if m is not None else print(m) "bat" >>> m = re.match(bt, "blt") # 不能匹配 >>> m.group() if m is not None else print(m) None >>> m = re.match(bt, "He bit me") # 不能匹配 >>> m.group() if m is not None else print(m) None >>> m = re.search(bt, "He bit me") # 可以搜索到 >>> m.group() if m is not None else print(m) "bit"匹配任何單個字符
點號.不能匹配換行符和空字符串。
>>> dote = ".end" >>> m = re.match(dote, "bend") # OK >>> m.group() if m is not None else print(m) "bend" >>> m = re.match(dote, "end") # 不能匹配空內容 >>> m.group() if m is not None else print(m) None >>> m = re.match(dote, " end") # 不能匹配換行符 >>> m.group() if m is not None else print(m) None >>> m = re.search(dote, "The end.") # 搜索匹配 >>> m.group() if m is not None else print(m) " end"
使用轉義符,匹配點號。
>>> pi = "3.14" >>> pit = "3.14" >>> m = re.match(pit, "3.14") # 精確匹配 >>> m.group() if m is not None else print(m) "3.14" >>> m = re.match(pi, "3014") # 點號匹配0 >>> m.group() if m is not None else print(m) "3014" >>> m = re.match(pi, "3.14") # 點號匹配. >>> m.group() if m is not None else print(m) "3.14"創建字符集
>>> selc = "[cr][23][dp][o2]" >>> m = re.match(selc, "c3po") >>> m.group() if m is not None else print(m) "c3po" >>> m = re.match(selc, "c3p1") >>> m.group() if m is not None else print(m) None重復、特殊字符以及分組
正則表達式中最常見的情況包括:
特殊字符的使用
正則表達式模式的重復出現
使用圓括號對匹配模式的各部分進行分組和提取操作
特殊字符與重復出現
匹配0~1個中間子域名
>>> import re >>> patt = "w+@(w+.)?w+.com" >>> m = re.match(patt, "nobody@xxx.com") # 匹配0個中間子域名 >>> m.group() if m is not None else print(m) "nobody@xxx.com" >>> m = re.match(patt, "nobody@xxx.yyy.com") # 匹配1個中間子域名 >>> m.group() if m is not None else print(m) "nobody@xxx.yyy.com" >>> m = re.match(patt, "nobody@xxx.yyy.zzz.com") # 不能匹配2個中間子域名 >>> m.group() if m is not None else print(m) None
匹配任意多個子域名
>>> patt = "w+@(w+.)*w+.com" # 將 ? 替換為 * >>> m = re.match(patt, "nobody@xxx.yyy.zzz.com") # 匹配2個中間子域名 >>> m.group() if m is not None else print(m) "nobody@xxx.yyy.zzz.com"
分組
使用圓括號來匹配和保存子組,以便于后續處理。
使用group()和groups()方法獲取分組,其兩者區別:
group()
訪問每個獨立的子組
獲取完整匹配(不傳遞參數)
groups()
獲取一個包含所有匹配子組的元組
>>> m = re.match("(www)-(ffffd)", "abc-123") >>> m.group() # 完整匹配 "abc-123" >>> m.group(1) # 子組1 "abc" >>> m.group(2) # 子組2 "123" >>> m.groups() # 全部子組 ("abc", "123")
一個完整示例
>>> m = re.match("ab", "ab") # 沒有分組 >>> m.group() # 完整匹配 "ab" >>> m = re.match("ab", "ab") # 沒有分組 >>> m.group() # 完整匹配 "ab" >>> m.groups() # 所有子組 () >>> >>> m = re.match("(ab)", "ab") # 一個子組 >>> m.group() # 完整匹配 "ab" >>> m.group(1) # 子組1 "ab" >>> m.groups() # 全部子組 ("ab",) >>> >>> m = re.match("(a)(b)", "ab") # 兩個子組 >>> m.group() "ab" >>> m.group(1) # 子組1 "a" >>> m.group(2) # 子組2 "b" >>> m.groups() # 全部子組 ("a", "b") >>> >>> m = re.match("(a(b))", "ab") # 兩個嵌套子組 >>> m.group() # 完整匹配 "ab" >>> m.group(1) # 子組1 "ab" >>> m.group(2) # 子組2 "b" >>> m.groups() # 全部子組 ("ab", "b")匹配字符串的起始和結尾以及單詞邊界
>>> m = re.search("^The", "The end.") # 匹配 >>> m.group() if m is not None else print(m) "The" >>> m = re.search("^The", "end. The") # 不做為開始 >>> m.group() if m is not None else print(m) None >>> m = re.search(r"the", "bite the dog") # 匹配左側邊界 >>> m.group() if m is not None else print(m) "the" >>> m = re.search(r"the", "bitethe dog") # 匹配左側邊界 >>> m.group() if m is not None else print(m) None >>> m = re.search(r"Bthe", "bitethe dog") # 匹配左側沒有邊界 >>> m.group() if m is not None else print(m) "the" >>> m = re.search(r"BtheB", "bitethe dog") # 匹配兩側沒有邊界 >>> m.group() if m is not None else print(m) None >>> m = re.search(r"Bthe", "bitethe dog") # 匹配左側沒有邊界,右側有邊界 >>> m.group() if m is not None else print(m) "the"使用findall和finditer查找每一次出現的位置
findall()
查詢字符串中某個正則表達式模式全部的非重復出現情況
與match()和search()的區別是,findall()總是返回一個列表
finditer()與findall()類似,不過返回結果是一個迭代器。
>>> re.findall("car", "car") ["car"] >>> re.findall("car", "carry") ["car"] >>> re.findall("car", "carry the barcardi to the car") ["car", "car", "car"]
結合分組使用
>>> s = "This and that." >>> re.findall(r"(thw+) and (thw+)", s, re.I) [("This", "that")] >>> list(re.finditer(r"(thw+) and (thw+)", s, re.I))[0].groups() ("This", "that") >>> list(re.finditer(r"(thw+) and (thw+)", s, re.I))[0].group(1) "This" >>> list(re.finditer(r"(thw+) and (thw+)", s, re.I))[0].group(2) "that"
單個分組的多重匹配
如果模式中只有一個分組,則匹配結果作為結果集合的單個元素
如果模式中由多個分組,則匹配結果為元組,作為結果集的單個元素
>>> s = "this and that" >>> re.findall(r"(thw+) and (thw+)", s, re.I) [("this", "that")] >>> re.findall(r"(thw+)", s, re.I) ["this", "that"] >>> >>> >>> s = "This and that. What, where, when, and who" >>> re.findall(r"thw+|whw+", s, re.I) ["This", "that", "What", "where", "when", "who"] >>> re.findall(r"(thw+)|(whw+)", s, re.I) [("This", ""), ("that", ""), ("", "What"), ("", "where"), ("", "when"), ("", "who")] >>> re.findall(r"(whw+)", s, re.I) ["What", "where", "when", "who"] >>> >>> >>> s = "This where. That when. There who." >>> re.findall(r"(thw+)s(whw+)", s, re.I) [("This", "where"), ("That", "when"), ("There", "who")]使用sub和subn搜索和替換
有兩個函數用于實現搜索和替換功能: sub() 和 subn()。sub()返回一個替換后的字符串;subn()還返回一個表示替換的總數,替換后的字符串和替換總數作為元組返回。
>>> re.sub("X", "Mr. Smith", "attn: X Dear X, ") "attn: Mr. Smith Dear Mr. Smith, " >>> re.subn("X", "Mr. Smith", "attn: X Dear X, ") ("attn: Mr. Smith Dear Mr. Smith, ", 2) >>> re.sub("[ae]", "X", "abcdef") "XbcdXf" >>> re.subn("[ae]", "X", "abcdef") ("XbcdXf", 2)
使用匹配對象的group()方法除了能夠取出匹配分組編號外,還可以使用N,其中N是在替換字符串中使用的分組編號。
>>> re.sub(r"(d{1,2})/(d{1,2})/(d{2}|d{4})", r"2/1/3", "2/20/1992") "20/2/1992" >>> re.sub(r"(d{1,2})/(d{1,2})/(d{2}|d{4})", r"2/1/3", "2/20/92") "20/2/92"在限定模式上使用split分隔字符串
split 基于正則表達式的模式分隔字符串??梢酝ㄟ^為max參數設定一個值(非零)來指定最大分割數。
>>> import re >>> DATA = () >>> DATA = ( ... "Mountain View, CA 94040", ... "Sunnyvale, CA", ... "Los Altos, 94023", ... "Cupertino 95014", ... "Palo Alto CA" ... ) >>> for datum in DATA: ... print(re.split(", |(?= (?:d{5}|[A-Z]{2})) ", datum)) ... ["Mountain View", "CA", "94040"] ["Sunnyvale", "CA"] ["Los Altos", "94023"] ["Cupertino", "95014"] ["Palo Alto", "CA"]擴展符號
通過使用(?iLmsux)系列選項,用戶可以直接在正則表達式里面指定一個或者多個標記。
re.I/re.IGNORECASE, re.M/MULTILINE
>>> re.findall(r"(?i)yes", "yes? Yes. YES!~") # 忽略大小寫 ["yes", "Yes", "YES"] >>> re.findall(r"(?i)thw+", "The quickest way is through this tunnel.") # 忽略大小寫 ["The", "through", "this"] >>> re.findall(r"(?im)(^th[w ]+)", """ # 忽略大小寫;多行 ... This line is the first, ... another line, ... that line, it"s the best. ... """) ["This line is the first", "that line"]
re.S/re.DOTALL
使用re.S,re.DOTALL標記,使得點號.能夠用來表示換行符。
>>> re.findall(r"th.+", """ ... The first line ... the second line ... the third line ... """) ["the second line", "the third line"] >>> re.findall(r"(?s)th.+", """ ... The first line ... the second line ... the third line ... """) ["the second line the third line "]
re.X/re.VERBOSE
re.X/re.VERBOSE標記允許用戶通過抑制在正則表達式中使用空白符(除了在字符類中或者在反斜線轉義中)來創建更易讀的正則表達式。
>>> re.search(r"""(?x) ... ((d{3})) # 匹配區號 ... [ ] # 匹配空格 ... (d{3}) # 匹配前綴 ... - # 橫線 ... (d{4}) # 終點數字 ... """, "(800) 555-1212").groups() ("800", "555", "1212")
(?:...)
通過使用(?:...)符號,可以對部分正則表達式進行分組,但是并不會保存該分組用于后續的檢索或應用。
>>> re.findall(r"http://(?:w+.)*(w+.com)", ... "http://goole.com http://www.google.com http://code.google.com") ["goole.com", "google.com", "google.com"] >>> re.search(r"((?Pd{3})) (?P d{3})-(?:d{4})", ... "(800) 555-1212").groupdict() {"areacode": "800", "prefix": "555"}
結合g,使用(?P
>>> re.sub(r"((?Pd{3})) (?P d{3})-(?:d{4})", ... "(g ) g -xxxx", "(800) 555-1212") "(800) 555-xxxx"
檢索元組
對于沒有命名的元組,使用N,其中N為數字
對于命名的元組,可以使用g
>>> m = re.search(r"(d{4}) (?Pd{4}) (d{3})", "0530 8023 123") >>> m.group() "0530 8023 123" >>> m.group(1) "0530" >>> m.group(2) "8023" >>> m.group(3) "123" >>> m.groupdict() {"prefix": "8023"} >>> >>> re.sub(r"(d{4}) (d{4}) (d{3})", r"3 2 1", "0530 8023 123") "123 8023 0530" >>> re.sub(r"(d{4}) (?P d{4}) (d{3})", r"3 2 1 - g ", "0530 8023 123") "123 8023 0530 - 8023"
在一個相同的正則表達式中重用模式。
>>> re.match(r"(?Pd{2})(?P=num)", "1212") # 只能匹配相同的內容 >>> print(m) if m is None else m.group() "1212" >>> m = re.match(r"(?P d{2})(?P=num)", "1234") # 不能匹配不同的內容 >>> print(m) if m is None else m.group() None
>>> bool(re.match(r"((?Pd{3})) (?P d{3})-(?P d{4}) (?P=areacode)-(?P=prefix)-(?P=number)", ... "(800) 555-1212 800-555-1212")) True >>> bool(re.match(r"""(?x) ... # match (800) 555-1212, save areacode, prefix, no. ... ((?P d{3}))[ ](?P d{3})-(?P d{4}) ... ... # space ... [ ] ... ... # match 800-555-1212 ... (?P=areacode)-(?P=prefix)-(?P=number) ... ... # space ... [ ] ... ... # match 18005551212 ... 1(?P=areacode)(?P=prefix)(?P=number) ... """, "(800) 555-1212 800-555-1212 18005551212")) True
前視匹配
可以使用(?=...) 和 (?!...) 符號在目標字符串中實現一個前視匹配,而不必實際使用這些字符串。
(?=...) : 正向前視斷言
(?!...) : 負向前視斷言
>>> re.findall(r"w+(?= van Rossum)", # 正向前視斷言 ... """ ... Guido van Rossum ... Tim Peters ... Alex Martelli ... Just van Rossum ... Raymond Hettinger ... """) ["Guido", "Just"] >>> re.findall(r"(?m)^s+(?!noreply|postmaster)(w+)", # 負向前視斷言 ... """ ... sales@phptr.com ... postmaster@phptr.com ... eng@phptr.com ... noreply@phptr.com ... admin@phptr.com ... """) ["sales", "eng", "admin"] >>> ["%s@aw.com" % e.group(1) for e in ... re.finditer(r"(?m)^s+(?!noreply|postmaster)(w+)", ... """ ... sales@phptr.com ... postmaster@phptr.com ... eng@phptr.com ... noreply@phptr.com ... admin@phptr.com ... """)] ["sales@aw.com", "eng@aw.com", "admin@aw.com"]
條件正則表達式匹配
(?(id/name)yes-pattern|no-pattern)
Will try to match with yes-pattern if the group with given id or name exists, and with no-pattern if it doesn’t. no-pattern is optional and can be omitted. For example, (<)?(w+@w+(?:.w+)+)(?(1)>|$) is a poor email matching pattern, which will match with "" as well as "user@host.com", but not with "nor "user@host.com>".
>>> r = r"(<)?(w+@w+(?:.w+)+)(?(1)>|$)" >>> m = re.match(r, "貪婪搜索") >>> print(m) if m is None else m.group() " " >>> m = re.match(r, "user@host.com") >>> print(m) if m is None else m.group() "user@host.com" >>> m = re.match(r, " >> print(m) if m is None else m.group() None >>> m = re.match(r, "user@host.com>") >>> print(m) if m is None else m.group()
加入由一系列類似如下格式的字符串
Thu Feb 15 17:32:12 2007::szhkai@qq.com::1123242-3-5
我們所感興趣的是,數據記錄內包含由連字符連接的三個整數的整行數據
>>> s = """ Thu Feb 15 17:41:42 2007::szhkai@qq.com::1123242-3 Sun Jul 22 13:32:25 2007::szhkai@qq.com::1123242-5 The May 12 17:02:52 2007::szhkai@qq.com::1123242-3-5 Thu Apr 18 12:22:42 2007::szhkai@qq.com::12323-3-5 """ >>> re.findall(r"(?m).+d+-d+-d+", s) [" The May 12 17:02:52 2007::szhkai@qq.com::1123242-3-5", " Thu Apr 18 12:22:42 2007::szhkai@qq.com::12323-3-5"]
如果我們對d+-d+-d+這一部分感興趣,可以使用元組提取
>>> re.findall(r"(?m).+(d+-d+-d+)", s) ["2-3-5", "3-3-5"]
但是不能提取第一個整數。這是因為正則表達式在實現上是采用貪婪匹配,試圖匹配該模式盡可能多的字符。可以使用非貪婪操作符?解決這個問題??梢栽?b>*, +, ?后使用?。該操作符要求正則表達式引擎匹配盡可能少的字符。在.+后放置一個?可以獲得期望的結果。
>>> re.findall(r"(?m).+?(d+-d+-d+)", s) ["1123242-3-5", "12323-3-5"]注意事項
ASCII碼沖突
如果符號同時使用于ASCII碼和正則表達式特殊符號,就會出現問題,如表示ASCII字符的退格符,但是同時也是一個正則表達式的特殊符號,表示匹配一個單詞的邊界。對于正則表達式編譯器而言,若將視為正則表達式特殊字符,需要使用進行轉義。
>>> m = re.match("blow", "blow") # 退格鍵; 沒有匹配 >>> print(m) if m is None else m.group() None >>> m = re.match("blow", "blow") # 匹配單詞邊界 >>> print(m) if m is None else m.group() "blow" >>> m = re.match(r"blow", "blow") # 使用 raw string >>> print(m) if m is None else m.group() "blow"
w和W字母數字字符集同時受re.L/LOCALE和Unicode(re.U/UNICODE)標記影響。
參考《Python 核心編程》
Python文檔
說明 Python版本# 對于Python2 bovenson@ThinkCentre:~$ python2 Python 2.7.13+ (default, Jul 19 2017, 18:15:03) [GCC 6.4.0 20170704] on linux2 Type "help", "copyright", "credits" or "license" for more information. # 對于Python3 bovenson@ThinkCentre:~$ python3 Python 3.5.4rc1 (default, Jul 25 2017, 08:53:34) [GCC 6.4.0 20170704] on linux Type "help", "copyright", "credits" or "license" for more information.
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/44736.html
摘要:正則表達式關閉或可選標志。如果所含正則表達式,以表示,在當前位置成功匹配時成功,否則失敗。否則指的是八進制字符碼的表達式。 正則表達式是個很牛逼的東西,不管是在javascript,還是在Python web開發(http://www.maiziedu.com/course/python-px...)中,我們都會遇到正則表達式,雖然javascript和Python的正則表達式區別不大...
摘要:反斜杠的困擾與大多數編程語言相同,正則表達式里使用作為轉義字符,這就可能造成反斜杠困擾。文本中正則表達式結束搜索的索引。以元組形式返回全部分組截獲的字符串。用于指定最大分割次數,不指定將全部分割。 1. 正則表達式基礎 1.1. 簡單介紹 正則表達式并不是Python的一部分。正則表達式是用于處理字符串的強大工具,擁有自己獨特的語法以及一個獨立的處理引擎,效率上可能不如str自帶的方法...
摘要:標記一個子表達式的開始和結束位置。用和進行搜索和替換二者幾乎是一樣的,都是將某字符串中所有匹配正則表達式模式的部分進行替換。 【未完成初稿】這周在工作中遇到很多需要從一段字符中增刪查改的工作,第一遍用自己寫的腳本去做,結果是可重用性不高,而且效率也不太好。其中也用到了python中的正則表達式部分re,后來就想能不能將我遇到的這類問題全部用正則去解決,具體就是python的re模塊。答...
摘要:正則表達式語法字符與字符類特殊字符以上特殊字符要想使用字面值,必須使用進行轉義字符類包含在中的一個或者多個字符被稱為字符類,字符類在匹配時如果沒有指定量詞則只會匹配其中的一個。 1. 正則表達式語法 1.1 字符與字符類 1 特殊字符:.^$?+*{}| 以上特殊字符要想使用字面值,必須使用進行轉義 2 字符類 1. 包含在[]中的一個或者多個字符被稱為字符類,字符類在匹配時如果沒有指...
摘要:在中,使用的內置模塊處理正則表達式操作。使用正則表達式對象在字符串中搜索模式。編寫和使用正則表達式在中創建正則表達式的第一步是導入模塊正則表達式使用模式字符串表示,模式字符串是指定所需搜索模式的字符串。 showImg(https://segmentfault.com/img/remote/1460000019166945?w=504&h=300); 來源 | 愿碼(ChainDes...
摘要:假設現在想把字符串你好,,世界中的中文提取出來,可以這么做你好,,世界注意到,我們在正則表達式前面加上了兩個前綴,其中表示使用原始字符串,表示是字符串。本文標題為正則表達式模塊簡明筆記本文鏈接為參考資料正則表達式 簡介 正則表達式(regular expression)是可以匹配文本片段的模式。最簡單的正則表達式就是普通字符串,可以匹配其自身。比如,正則表達式 hello 可以匹配字符...
閱讀 3149·2021-11-22 13:54
閱讀 3435·2021-11-15 11:37
閱讀 3598·2021-10-14 09:43
閱讀 3496·2021-09-09 11:52
閱讀 3595·2019-08-30 15:53
閱讀 2457·2019-08-30 13:50
閱讀 2055·2019-08-30 11:07
閱讀 886·2019-08-29 16:32