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,}$ 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM