正則表達式 正則表達式:一種字元串匹配的規則 字元組 字元 註意這三種的結果都表示匹配所有:[\d\D]、[\s\S]、[\w\W] 量詞 貪婪匹配 貪婪匹配:在滿足匹配時,匹配儘可能長的字元串,預設情況下,採用貪婪匹配 . *?的用法 re模塊 在python中用來提供正則表達式匹配的模塊就是re ...
正則表達式
正則表達式:一種字元串匹配的規則
字元組
字元組 : [字元組] 在同一個位置可能出現的各種字元組成了一個字元組,在正則表達式中用[]表示 字元分為很多類,比如數字、字母、標點等等。 假如你現在要求一個位置"只能出現一個數字",那麼這個位置上的字元只能是0、1、2...9這10個數之一。
正則 | 待匹配字元 | 匹配結果 | 說明 |
[0123456789] | 6 | True | 在一個字元組裡枚舉合法的所有字元,字元組的任意一個字元和"待匹配字元"相同都視為可匹配 |
[0123456789] | a | False | 由於字元組中沒有“a”,所以不能匹配 |
[0-9] | 7 | True | 匹配0-9中的任意數字;等於[0123456789] |
[a-z] | s | True | 匹配a-z中任意小寫字母。 |
[A-Z] | B | True | 匹配A-Z中任意大寫字母。 |
[0-9a-zA-Z] | e | True | 匹配任意數字、大小寫字母。 |
字元
元字元 | 匹配內容 |
. | 匹配除換行符以外的任意字元 |
\w | 匹配字母或數字或下劃線 |
\s | 匹配任意的空白符:空格、tab、換行;等於[\f\n\r\t] |
\d | 匹配數字;等於[0-9] |
\W | 匹配非字母或數字或下劃線,也就是說除了字母、數字、下劃線以外的 |
\S | 匹配非任意的空白符,也就是說除了空格、tab、換行以外的;等於[^ \f\n\r\t] |
\D | 匹配非數字,也就是說除了數字以外的 |
\t | 匹配一個製表符,tab |
\n | 匹配一個換行符 |
^ | 匹配字元串以什麼開頭的 |
$ | 匹配字元串以什麼結尾的 |
a|b | 匹配字元a或者字元b,| 或者的關係 |
() | 匹配括弧內的表達式,也表示一個組 |
[...] | 匹配字元組中的字元 |
[^...] | 匹配非字元組中的所有字元 |
\b | 匹配一個單詞的邊界 |
註意這三種的結果都表示匹配所有:[\d\D]、[\s\S]、[\w\W]
量詞
量詞 | 用法說明 |
* | 重覆零次或者多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等價於{0,}。 |
+ | 重覆一次或者多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價於 {1,}。 |
? | 重覆零次或者一次。例如,"do(es)?" 可以匹配 "do" 、 "does" 中的 "does" 、 "doxy" 中的 "do" 。? 等價於 {0,1}。 |
{n} | 重覆n次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的兩個 o。 |
{n,} | 重覆n次或多次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等價於 'o+'。'o{0,}' 則等價於 'o*'。 |
{n,m} | 重覆n次到m次。例如,"o{1,3}" 將匹配 "fooooood" 中的前三個 o。'o{0,1}' 等價於 'o?'。請註意在逗號和兩個數之間不能有空格。 |
貪婪匹配
貪婪匹配:在滿足匹配時,匹配儘可能長的字元串,預設情況下,採用貪婪匹配
正則 | 待匹配字元 | 匹配結果 | 說明 |
<.*> | <abcdefg>2<hijklmn> | <abcdefg>2<hijklmn> | 預設為貪婪模式,會匹配儘量長的字元串 |
<.*?> | <abcdefg>2<hijklmn> | <abcdefg> | 加上? 為了將貪婪匹配模式轉為非貪婪匹配模式,會匹配儘量短的字元串 |
幾個常用的非貪婪匹配Pattern
*? 重覆任意次,但儘可能少重覆 +? 重覆1次或更多次,但儘可能少重覆 ?? 重覆0次或1次,但儘可能少重覆 {n,m}? 重覆n到m次,但儘可能少重覆 {n,}? 重覆n次以上,但儘可能少重覆
. *?的用法
. 是任意字元 * 是取 0 至 無限長度 ? 是非貪婪模式。 何在一起就是 取儘量少的任意字元,一般不會這麼單獨寫,他大多用在: .*?x 就是取前面任意長度的字元,直到一個x出現
re模塊
在python中用來提供正則表達式匹配的模塊就是re模塊
在re模塊中的匹配語法有以下幾種
- re.match:從頭開始匹配,匹配成功返回正則匹配成功的對象,匹配失敗返回None
- re.search:匹配包含的所有,匹配成功返回正則匹配成功的對象,匹配失敗返回None
- re.findall:將所有匹配到的字元以一個列表的形式返回,匹配失敗返回一個空列表
- re.finditer:和findall類似,將匹配到的所有字元作為一個迭代器返回
- re.split:按照能夠匹配的子串將字元串分割後返回列表
- re.sub:匹配字元並替換
- re.compile:編譯正則表達式,生成一個正則表達式( Pattern )對象,供 match() 和 search() 這兩個函數使用。
re.findall函數 *****
- 格式:re.findall(pattern, string, flags=0)
- 參數:
pattern:匹配的正則表達式 string:要匹配的字元串 flags:標誌位,用於控制正則表達式的匹配方式,可有可無
標誌位常見取值如下:re.I 忽略大小寫 re.L 作本地戶識別 re.M 多行匹配,影響^和$ re.S 使.匹配包括換行符在內的所有字元 re.U 根據Unicode字元集解析字元,影響\w \W \b \B re.X 使我們以更靈活的格式理解正則表達式
- 示例:
ret = re.findall(r'\d+', 'Today454 is1 a 00 day3') # 匹配一位到多位的數字 print(ret) # 結果>>> ['45', '1', '00', '3'] ret = re.findall(r'[a-z]{3}', 'Today is a Good day, Day') # 匹配任意連續三個小寫字母 print(ret) # 結果>>> ['oda', 'ood', 'day'] ret = re.findall(r'[a-z]{3}', 'Today is a Good day, Day', flags=re.I) # 匹配任意連續三個字母,不區分大小寫;flags=re.I表示不區分大小寫 print(ret) # 結果>>> ['Tod', 'Goo', 'day', 'Day']
- findall的優先順序查詢:
import re ret = re.findall('www.(baidu|souhu).com', 'www.baidu.com') print(ret) # 結果>>> ['baidu'] 這是因為findall會優先把匹配到的結果,組裡的內容返回;如果想要匹配結果,取消許可權即可 ret = re.findall('www.(?:baidu|souhu).com', 'www.baidu.com') print(ret) # 結果>>> ['www.baidu.com']
re.search函數 *****
- 格式:re.search(pattern, string, flags=0)
- 參數:
pattern:匹配的正則表達式 string:要匹配的字元串 flags:標誌位,用於控制正則表達式的匹配方式
- 示例:
ret = re.search(r'd', 'Today is a Good day, Day') print(ret) # 結果>>> <_sre.SRE_Match object; span=(2, 3), match='d'> print(ret.group()) # 結果>>> d ret = re.search(r'j', 'Today is a Good day, Day') print(ret) # 結果>>> None
re.match函數 ***
- 格式:re.match(pattern, string, flags=0)
- 參數:
pattern:匹配的正則表達式 string:要匹配的字元串 flags:標誌位,用於控制正則表達式的匹配方式
- 示例:
ret = re.match(r'www', 'www.baidu.com') print(ret) # 結果>>> <_sre.SRE_Match object; span=(0, 3), match='www'> print(ret.group()) # 結果>>> www ret = re.match(r'www', 'ww.baidu.com') print(ret) # 結果>>> None
re.sub函數 ***
- 格式:re.sub(pattern, repl, string, count=0)
- 參數:
pattern: 正則表達式(規則) repl: 指定的用來替換的字元串 string: 目標字元串 count: 最多替換次數,如果不指定,預設全部替換
- 示例:
ret = re.sub(r'\d', 'H', 'sjkd42jk234523jln5aex8439') print(ret) # 結果>>> sjkdHHjkHHHHHHjlnHaexHHHH ret = re.sub(r'\d', 'H', 'sjkd42jk234523jln5aex8439',count=2) print(ret) # 結果>>> sjkdHHjk234523jln5aex8439 # subn函數:其實和sub一樣,只是返回替換了多少次 ret = re.subn(r'\d', 'H', 'sjkd42jk234523jln5aex8439') print(ret) # 結果>>> ('sjkdHHjkHHHHHHjlnHaexHHHH', 13) ret = re.subn(r'\d', 'H', 'sjkd42jk234523jln5aex8439',count=2) print(ret) # 結果>>> ('sjkdHHjk234523jln5aex8439', 2)
re.split函數 ***
- 格式:re.split(pattern, string, maxsplit=0, flags=0)
- 參數:
pattern:匹配的正則表達式 string:要匹配的字元串 maxsplit : 指定分隔的次數;預設為0,不限制次數 flags:標誌位,用於控制正則表達式的匹配方式
- 示例:
ret = re.split(r'\d+', 'www232abcdw3jafe32ad') print(ret) # 結果>>> ['www', 'abcdw', 'jafe', 'ad'] ret = re.split(r'\d+', 'www232abcdw3jafe32ad', maxsplit=2) print(ret) # 結果>>> ['www', 'abcdw', 'jafe32ad']
- split的優先順序查詢
ret = re.split('\d+', 'sdjkfl3sdjl5jskd2dsf') print(ret) # 結果>>> ['sdjkfl', 'sdjl', 'jskd', 'dsf'] ret = re.split('(\d+)', 'sdjkfl3sdjl5jskd2dsf') print(ret) # 結果>>> ['sdjkfl', '3', 'sdjl', '5', 'jskd', '2', 'dsf'] ''' 在匹配部分加上()之後所切出的結果是不同的, 沒有()的沒有保留所匹配的項,但是有()的卻能夠保留了匹配的項, 這個在某些需要保留匹配部分的使用過程是非常重要的。 '''
re.compile函數 *****
- 格式:re.compile(pattern)
- 參數:
pattern:要編譯的正則表達式
- 示例:
my_re = re.compile('\d{3}') ret = re.findall(my_re, 'jdla2jd2462jskdf234546') print(ret) # 結果>>> ['246', '234', '546'] ret = re.search(my_re, 'jdla2jd2462jskdf234546').group() print(ret) # 結果>>> 246 ret = re.match(my_re, '43423sjdkfljaj24234').group() print(ret) # 結果>>> 434 # 編譯後的,都可以使用re模塊的其他方法,如:findall、search、match、sub、split等
re.finditer函數 *****
- 格式:re.finditer(pattern, string, flags=0)
- 參數:
pattern:匹配的正則表達式 string:要匹配的字元串 flags:標誌位,用於控制正則表達式的匹配方式
- 示例:
ret = re.finditer(r'\d', 'sjkdfl3jskl9ajkl234jdkf75jdslf') for i in ret: print(i.group()) # 結果>>> ''' 3 9 2 3 4 7 5 '''
分組 *****
除了簡單地判斷是否匹配之外,正則表達式還有提取子串的強大功能。用()
表示的就是要提取的分組
str3 = "010-52365561" m = re.match(r"(\d{3})-(\d{8})", str3) c = re.match(r"(?P<first>\d{3})-(\d{8})", str3) # ?P<>給組起名 print(m) # 列印結果:<_sre.SRE_Match object; span=(0, 12), match='010-52365561'> print(m.group(0)) #使用序號獲取對應組的信息,group(0)--代表原始的字元串 # 列印結果:010-52365561 print(m.group(1)) # 列印結果:010 print(m.group(2)) # 列印結果:52365561 print(m.groups()) #查看匹配的各組的情況 # 列印結果:('010', '52365561') print(c.group("first")) # 列印結果:010
擴展
匹配標簽
ret = re.search(r'<(?P<tag_name>\w+)>.+</(?P=tag_name)>', '<h1>Hello World</h1>') ''' 還可以在分組中利用?<name>的形式給分組起名字 獲取的匹配結果可以直接用group('名字')拿到對應的值 ''' print(ret.group()) # 結果>>> <h1>Hello World</h1> print(ret.group('tag_name')) # 結果>>> h1 ret = re.search(r'<(\w+)>.+</(\1)>', '<h1>Hello World</h1>') ''' 如果不給組起名字,也可以用\序號來找到對應的組,表示要找的內容和前面的組內容一致 獲取的匹配結果可以直接用group(序號)拿到對應的值 ''' print(ret.group()) # 結果>>> <h1>Hello World</h1> print(ret.group(1)) # 結果>>> h1
匹配整數
ret = re.findall('\d+', "1-2*(60+(-40.35/5)-(-4*3))") print(ret) # 結果>>> ['1', '2', '60', '40', '35', '5', '4', '3'] ret = re.findall('-?\d+\.\d+|(-?\d+)', "1-2*(60+(-40.35/5)-(-4*3))") print(ret) # 結果>>> ['1', '-2', '60', '', '5', '-4', '3'] ret.remove('') print(ret) # 結果>>> ['1', '-2', '60', '5', '-4', '3']
數字匹配
1、 匹配一段文本中的每行的郵箱 http://blog.csdn.net/make164492212/article/details/51656638 2、 匹配一段文本中的每行的時間字元串,比如:‘1990-07-12’; 分別取出1年的12個月(^(0?[1-9]|1[0-2])$)、 一個月的31天:^((0?[1-9])|((1|2)[0-9])|30|31)$ 3、 匹配qq號。(騰訊QQ號從10000開始) [1,9][0,9]{4,} 4、 匹配一個浮點數。 ^(-?\d+)(\.\d+)?$ 或者 -?\d+\.?\d* 5、 匹配漢字。 ^[\u4e00-\u9fa5]{0,}$