[Python] 正規表示法 Regular Expression

程式語言:Python
Package:re

re 官方文件

debug online:
Debuggex
regex101

功能:處理匹配字串
  1. import re
  2. re.search(pattern, string)

語法

-------------------------------------------------------------------------------------

'.'
  • 匹配除「\n」之外的任何單個字符
  • 例: a.c 匹配 abc1234 => abc

'^'
  • 匹配輸入字串的開始位置
  • 設定 RegExp 物件的 Multiline 屬性,可匹配「\n」或「\r」之後的位置
  • 例: ^ab 匹配 abc1234 => ab

'$'
  • 匹配輸入字串的結束位置
  • 設定 RegExp 物件的 Multiline 屬性,可匹配「\n」或「\r」之前的位置
  • 例: 34$ 匹配 abc1234 => 34

'*'
  • 匹配至少零次
  • 例: ac* 匹配 abc1234 => a

'+'
  • 匹配至少一次
  • 例: ab.+ 匹配 abc1234 => abc1234

'?'
  • 匹配零次或一次
  • 例: ab? 匹配 abc1234 => ab

'*?' '+?' '??'
  • 匹配模式是 non-greedy,符合的最少字串,預設為 greedy
  • 可用在(*,+,?,{n},{n,},{n,m})後面
  • 例: a+? 匹配 aaaaa => a

{m}
  • 匹配 m 次
  • 例: a{3} 匹配 aaaaa => aaa

{m,n}
  • 匹配次數介於 m & n 之間,省略 n 表示無限次
  • 例: a{1,3} 匹配 aaaaa => aaa

'\'
  • 使用限制字元
  • 例: a\+ 匹配 a+aaaa => a+

[]
  • 匹配字元集合
  • - 表示從某字元到某字元,例:[a-z]
  • ^ 表示排除字元,例:[^a-z],需放置最前面,不然當作字元 '^'
  • 例: [a\-z]b 匹配 a-baaa => -b

'|'
  • 例: (a|b)aa 匹配 a-baaa => baa

(...)
  • 取得匹配的子字串,並放進 group
  • 例: (a|b)aa 匹配 a-baaa => baa, \1 = b (match.group(0) = baa, match.group(1) = b)

(?aiLmsux)
  • 指定匹配方式
  • (?a) 讓 \w, \W, \b, \B, \d, \D, \s and \S 只依 ASCII 匹配
  • (?i) 忽略大小寫
  • (?L) 讓 \w, \W, \b, \B, \s and \S 依本地字符編碼 (Python 3.6 已被移除)
  • (?m) ^ $ 匹配不同行的頭和尾
  • (?s) '.' 匹配全部,包括 \n
  • (?u) unicode 匹配 (Python 3 已移除,預設已為 unicode 匹配)
  • (?x) 忽略空白字符,且可以用 # 當作註解,可多行建立 pattern,利用 """abc string"""
    • 例: (?x)t es #測試 匹配 test => tes
  • 可同時使用,例:(?imx)^aa 匹配 a-bA\n#AA => None 因 AA 被註解

(?:...)
  • 不取得匹配的子字串
  • 例: (?:a|b|c)1 匹配 abc1234 => c1

(?P<name>)

  • 增加別名
  • 例: (?P<aa>a|b|c)1 匹配 abc1234 => c1, group('aa') = c

(?P=name)
  • 與別名的字串匹配
  • 例: (?P<aa>a|b|c)1234(?P=aa) 匹配 abc1234c => c1234c

(?#...)
  • 註解
  • 例: (?P:a|b|c)(?#comment)1234 匹配 abc1234 => c1234

(?=...)
  • 之後的字串需匹配,但不消耗字串且不放進 group
  • 例: abc(?=1234)123 匹配 abc1234 => abc123

(?!...)
  • 之後的字串需不匹配,但不消耗字串且不放進 group
  • 例: ab(?!\d).123 匹配 abc1234 => abc123

(?<=...)
  • 之前的字串需匹配,但不消耗字串且不放進 group
  • 例: c(?<=abc)123 匹配 abc1234 => c123

(?<!...)
  • 之前的字串需不匹配,但不消耗字串且不放進 group
  • 例: (?<!\d)c123 匹配 abc1234 => c123

(?(id/name)yes-pattern|no-pattern)
  • 若子字串匹配成立,則為 yes-pattern 否則為 no-pattern (可省略)
  • 例: (\d)?abc(?(1)\d|) 匹配 1abc1 或 abc 或 1abc 或 abc1

\A
  • 匹配輸入字串的開始位置,不受 Multiline 影響
  • 例: (?m)\Aabc 匹配 de\nabc => None

\b
  • 匹配單詞的開頭或結尾,也就是單詞的分界處
  • \b 在字符類裡使用代表退格,故建議使用 r'string' 或 \
  • 例: \bhi\b.* 匹配 history, hi a => hi a

\B
  • 匹配不是單詞開頭或結束的位置
  • 例: \B1234\B. 匹配 1234a1234c => 1234c

\d
  • 匹配數字 unicode 包括全部數字,在 (?a) 下同 [0-9]
  • unicode 數字
  • 例: 1\d 匹配 1234 => 12

\D
  • 匹配非數字 unicode 包括全部數字,在 (?a) 下同 [^0-9]
  • unicode 數字
  • 例: a\D 匹配 abc => ab

\s
  • 匹配空白字符 unicode 包括全部空白字符,在 (?a) 下同 [ \t\n\r\f\v]
  • unicode 空白字符
  • 例: a\s 匹配 a\nbc => a\n

\S
  • 匹配非空白字符 unicode 包括全部空白字符,在 (?a) 下同 [^ \t\n\r\f\v]
  • unicode 空白字符
  • 例: b\S 匹配 a\nbc => bc

\w
  • 匹配 word, unicode 包括全部 word,在 (?a) 下同 [a-zA-Z0-9_]
  • 例: b\w 匹配 a\nbc => bc

\W
  • 匹配非 word, unicode 包括全部 word,在 (?a) 下同 [^a-zA-Z0-9_]
  • 例: a\W 匹配 a\nbc => a\n

\Z
  • 匹配輸入字串的結尾位置,不受 Multiline 影響
  • 例: (?m)de\Z 匹配 de\nabc => None

re Module

-------------------------------------------------------------------------------------
簡單範例
  1. import re
  2. # 編譯成 Pattern 對象
  3. pattern = re.compile(r'hello')
  4. # 取得匹配結果,無法匹配返回 None
  5. match = pattern.match('hello world!')
  6. if match:
  7. # 得到匹配結果
  8. print(match.group())


flags 設定,可同時使用,用 | 隔開
  • re.A(re.ASCII) 同(?i)
  • re.I(re.IGNORECASE) 同(?i)
  • re.L(re.LOCALE) 同(?L)
  • re.M(re.MULTILINE) 同(?m)
  • re.S(re.DOTALL) 同(?s)
  • re.U(re.UNICODE) 同(?u)
  • re.X(re.VERBOSE) 同(?x)
  • re.DEBUG:顯示 pattern 的邏輯


re.compile(pattern, flags=0)
  1. import re
  2. pattern = re.compile(r'hello', re.I | re.M)
  3.  
  4. pattern = re.compile(r"""\d + # 數字部分
  5. \. # 小數點
  6. \d * # 小數部分""", re.X)


re.escape(string)
  1. import re
  2. str = '(123)'
  3. # 除了英文字母、數字和 '_' 以外,對所有字進行反斜線處理,可用在變數上
  4. pattern = re.escape(str) # '\\(123\\)'


re.search(pattern, string, flags=0)
  1. import re
  2. match = re.search(r'world', 'hello world!')


re.match(pattern, string, flags=0)
  1. import re
  2. # 從字串開頭找,結果會是 None
  3. match = re.match(r'world', 'hello world!')


re.fullmatch(pattern, string, flags=0)
  1. import re
  2. # 需完全符合
  3. match = re.fullmatch(r'hello world', 'hello world')


re.split(pattern, string, maxsplit=0, flags=0)
  1. import re
  2. # >> ['ab', 'cd', 'd']
  3. match = re.split(r'\d', 'ab2cd5d')


re.findall(pattern, string, flags=0)
  1. import re
  2. # >> ['2', '5']
  3. match = re.findall(r'\d', 'ab2cd5d')


re.finditer(pattern, string, flags=0)
  1. import re
  2. # iterator object
  3. match = re.finditer(r'\d', 'ab2cd5d')


re.sub(pattern, repl, string, count=0, flags=0)
template 可使用 \id 或 \g<id>、\g<name> 引用 group
\10 會認為是第 10 個 group,若表達 \1 接著是 '0',可使用 \g<1>0
  1. import re
  2. # >> 'ab_cd_d'
  3. str = re.sub(r'\d','_', 'ab2cd5d')


re.subn(pattern, repl, string, count=0, flags=0)
template 可使用 \id 或 \g<id>、\g<name> 引用 group
\10 會認為是第 10 個 group,若表達 \1 接著是 '0',可使用 \g<1>0
  1. import re
  2. #同 sub,但回傳 (newString, 取代次數) >> ('abc2dd5', 2)
  3. tupleA = re.subn(r'(\d)(.)',r'\2\1', 'ab2cd5d')

re Match Objects

-------------------------------------------------------------------------------------
match.expand(template)
template 可使用 \id 或 \g<id>、\g<name> 引用 group
\10 會認為是第 10 個 group,若表達 \1 接著是 '0',可使用 \g<1>0
  1. import re
  2. pattern = re.compile(r'(\w*) (\w*)')
  3. match = pattern.match('hello world!')
  4. # >> world hello
  5. print(match.expand(r'\2 \1'))


match.group([group1, ...])
  1. import re
  2. pattern = re.compile(r'(\w*) (\w*)(?P<tt>.*)')
  3. match = pattern.match('hello world!!!')
  4. # >> hello world
  5. print(match.group(0))
  6. # >> hello
  7. print(match.group(1))
  8. # >> world
  9. print(match.group(2))
  10. # >> !!!
  11. print(match.group(3))
  12. #同上 >> !!!
  13. print(match.group('tt'))


match.groups(default=None)
  1. import re
  2. pattern = re.compile(r'(\w*) (\w*)(?P<tt>.*)')
  3. match = pattern.match('hello world!!!')
  4. #>> ('hello', 'world', '!!!')
  5. print(match.groups())


match.groupdict(default=None)
  1. import re
  2. pattern = re.compile(r'(\w*) (\w*)(?P<tt>.*)')
  3. match = pattern.match('hello world!!!')
  4. #>> {'tt': '!!!'}
  5. print(match.groupdict())


match.start([group])
match.end([group])
match.span([group])
  1. import re
  2. pattern = re.compile(r'(\d*) (\d*)(?P<tt>.*)')
  3. match = pattern.match('012345 789!!')
  4. #第一個字符的索引 >> 7
  5. print(match.start(2))
  6. #最後一個字符的索引 + 1 >> 6
  7. print(match.end(1))
  8. #(start, end) >> (10, 12)
  9. print(match.span(3))
  10. #同上 >> (10, 12)
  11. print(match.span('tt'))
  12. #預設為 group(0) >> (0, 12)
  13. print(match.span())

參考:

正規表示式 - 維基百科
正則表達式30分鐘入門教程
Python正則表達式指南

留言