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

15-正則表示式

正則表示式三個方法

  • Regular Expression

    • 匹配有規則的字串
  • import re

  • re.match()

    • 匹配字串是否以指定正則表示式開頭
      • res = re.match('\d+', '123456') # object,返回物件或者None
  • re.search()

    • 匹配字串是否包含表示式

      • res2 = re.search('oog', 'google') # object,返回物件或者None

        • # re.I忽略大小寫
          res2 = re.search('GOO', 'google', re.I)  # object
          
  • re.findall()

    • 獲取所有匹配的子字串,返回的是列表
      • res3 = re.findall('goo', 'google google google') # ['goo', 'goo', 'goo'],如果匹配不到則返回空列表

匹配單個字元

  • .
    • . 表示匹配任意單個字元,除了換行\n
    • print(re.search('go.gle', 'go\ngle', re.S)) # 物件
      • re.S可以讓 . 匹配\n
  • []
    • 表示匹配單個字元的範圍
    • [abc]:匹配a或b或c
    • [a-zA-Z0-9_]:匹配數字字母下劃線
    • print(re.search('go[a-zA-Z0-9_]gle', 'go_gle')) # 物件
  • \d
    • 表示數字,等價於[0-9]
    • \D :表示非數字,等價於[^0-9]
    • print(re.search('go\dgle', 'go8gle')) # 物件
  • \w
    • 表示數字字母下劃線,等價於[a-zA-Z0-9_]
    • \W表示非數字字母下劃線,等價於[^a-zA-Z0-9_]
    • print(re.search('go\wgle', 'go8gle')) # 物件
  • \s
    • 表示空格 或換行\n 或 製表符\t 或 換頁符\f 回車符\r
    • \S表示非(空格 或換行\n 或 製表符\t 或 換頁符\f 回車符\r)
    • print(re.search('go\Sgle', 'go gle')) # None

表示數量的符號

  • ?
    • 表示前面的字元可以出現0次或1次
      • print(re.findall('go?gle', 'google')) # [] # 非貪婪(最多匹配一個)
    • 表示前面的字元可以出現1次或多次
    • print(re.findall('go+gle', 'gooogle')) # ['gooogle'] # 貪婪(儘量多個匹配)
    • *表示前面的字元可以出現0次或多次
      • print(re.findall('g.*gle', 'g123abc,.;gle')) # ['g123abc,.;gle']
  • {}
    • 表示前面字元出現的次數範圍
    • {3} :表示前面字元出現3次
    • {2, 5} :表示從2次~5次之間
    • {2,}
    • {,5}
      • print(re.findall('go{2,5}gle', 'gooogle')) # ['gooogle'],2和5之間不能加空格 # 貪婪

注意r''只能消除字串中的語義,不影響正則的語義,因此要匹配點(.),需要在點前加\

邊界符號(錨字元)

  • ^
    • ^ :開頭匹配
  • $
    • $ :結尾匹配
  • ^$
    • ^$ :完全匹配:除了正則中的字串以外,不可以有其他多餘的字元
  • 其他邊界字串
    • \A\Z
      • 與^$作用基本一致
      • 區別
        • print(re.findall('^#', '#google\n#baidu\n#360', re.M)) # ['#', '#', '#']
        • print(re.findall('\A#', '#google\n#baidu\n#360', re.M)) # ['#']
        • re.M
          • re.M: 換行模式
  • \b
    • 以單詞結尾
    • \B以非單詞結尾
  • chinesePattern = "[\u4e00-\u9fa5]+"

分組和捕獲

  • 分組

    • ()

      • () :表示整體,還可以表示分組

        • s = '0755-88888888'
          pattern = '(\d{4})-(\d{8})'
          # pattern = '\d{4}-\d{8}'
          res = re.search(pattern, s)
          
      • print(res.group()) # '0755-88888888'

      • print(res.group(0)) # '0755-88888888'

      • print(res.group(1)) # '0755', 第一個分組(第一個括號的內容)

      • print(res.group(2)) # '88888888', 第二個分組(第二個括號的內容)

      • print(res.groups()) # ('0755', '88888888'),獲取所有分組

  • 捕獲

    • 用findall(),返回列表

      • pattern = r'(\d+)萬到(\d+)萬盧比'
        res = re.findall(pattern, s)  # 捕獲()裡面的
        print(res)  # [('15', '40')]
        
      • 別名

        • ?P<別名>

          • pattern = r'(?P<start>\d+)萬到(?P<end>\d+)萬盧比'
            res = re.search(pattern, s)
            print(res.group('end'))  # 40
            print(res.group('start'))  # 15
            
  • 編譯正則

    • 編譯正則:建立一個正則表示式物件,效率更高

      • # re.compile()
        
        pattern = re.compile(r'(\d+)萬到(\d+)萬盧比')
        res = pattern.findall(s)
        print(res)  # [('15', '40')]
        
  • 非捕獲性分組

    • ?:

      • pattern = r'(\d+)萬到(?:\d+)萬盧比'
        res = re.findall(pattern, s)
        print(res)  # ['15']
        

其他正則函式

  • re.finditer

    • 匹配後的結果=>迭代器

      • res = re.finditer(r'\d+', '123abc456def678')
        print(res)  # 迭代器,<callable_iterator object at 0x0000026B6059F7C8>
        for i in res:
            # print(i)
            print(i.group(), i.span())
        '''
        123 (0, 3)
        456 (6, 9)
        678 (12, 15)
        '''
        
  • re.split

    • 分割/拆分

      • s = 'hello world'
        print(re.split(r'l|\s', s))  # ['he', '', 'o', 'wor', 'd']
        print(re.split(r'l|o', s))  # ['he', '', '', ' w', 'r', 'd']
        
      • |表示或者

  • re.sub

    • 替換

      • s = 'today is a good day today is a nice day'
        print(re.sub(r'\s', '-', s))  # today-is-a-good-day-today-is-a-nice-day
        print(re.subn(r'\s', '-', s))  # ('today-is-a-good-day-today-is-a-nice-day', 9)
        

補充

  • 空白行
    • \n\s*\r
  • 前後空白字串
    • ^\s*|\s*$
  • 零寬斷言
    • ?=exp
      • 斷言當前位置後面能匹配exp
    • ?<=exp
      • 斷言當前位置前面能匹配exp
    • ?!exp
      • 斷言當前位置後面不能匹配exp
    • ?<!exp
      • 斷言當前位置前面不能匹配exp