python語法
或 (or):| 管線符號,用來將所有可能的選擇條件分隔開。例如 gray|grey 可以用來匹配 gray 或是 grey 字串。
群組 (grouping):() 小括號,用來表示作用範圍或優先順序。例如 gray|grey 和 gr(a|e)y 都同樣可以用來匹配 gray 或是 grey 字串。
量詞 (quantifier):quantifier 用來接在字符串或群組後面,表示某個條件應該出現「幾次」。常見的量詞有:
?:表示連續出現 0 次或 1 次。例如 colou?r 可以用來匹配 color 或 colour。
:表示連續出現 0 次或多次。例如 abc 可以用來匹配 ac, abc, abbc, abbbc 或 abbbbbbc。
+:表示連續出現 1 次或多次。例如 ab+c 可以用來匹配 abc, abbc, abbbc, abbbbbbc,但 ac 不符合。
{min,max}:表示至少連續出現 min 次,但最多連續出現 max 次。
dot
點號 (dot or period) . 用來匹配除了換行符號 (line breaks) \n \r 之外的任何一個字元。
例子:
a.c 可以用來匹配 "abc", "aGc", "a c", "a5c", "a_c", "a#c" 等字串,但不能匹配 "a\nc"。
import re
bool(re.search('a.c', 'abc')) # True
bool(re.search('a.c', 'a#c')) # True
bool(re.search('a.c', 'a\nc')) # False
[\s\S] match any
[\s\S] 用來匹配任意一個字元,包含換行符號。
例子:
a[\s\S]c 可以用來匹配 "abc", "aGc", "a c", "a5c", "a_c", "a#c", "a\nc" 等字串。
import re
bool(re.search('a[\s\S]c', 'abc')) # True
bool(re.search('a[\s\S]c', 'a#c')) # True
bool(re.search('a[\s\S]c', 'a\nc')) # True
\w word (小寫)
\w 用來匹配所有大小寫英文字、阿拉伯數字和底線 _。
\w 意思同等於 [A-Za-z0-9_]。
例子:
pattern a\wc 可以用來匹配 "abc", "aGc", "a5c", "a_c" 等字串,但不能匹配 "a c", "a#c", "a\nc" 等字串。
import re
bool(re.search('a\wc', 'abc')) # True
bool(re.search('a\wc', 'a#c')) # False
bool(re.search('a\wc', 'a\nc')) # False
\W not word(大寫)
\W 用來匹配 \w 以外的所有字。
\W 意思同等於 [^A-Za-z0-9_]。
例子:
a\Wc 可以用來匹配 "a c", "a#c", "a\nc" 等字串,但不能匹配 "abc", "aGc", "a5c", "a_c" 等字串。
import re
bool(re.search('a\Wc', 'abc')) # False
bool(re.search('a\Wc', 'a#c')) # True
bool(re.search('a\Wc', 'a\nc')) # True
\d digit
\d 用來匹配所有阿拉伯數字 0-9。
\d 意思同等於 [0-9]。
例子:
a\dc 可以用來匹配 "a1c", "a5c" 等字串,但不能匹配 "abc", "aGc", "a_c", "a c", "a#c", "a\nc" 等字串。
import re
bool(re.search('a\dc', 'abc')) # False
bool(re.search('a\dc', 'a5c')) # True
bool(re.search('a\dc', 'a\nc')) # False
\D not digit
\D 用來匹配 \d 以外的所有字。
\D 意思同等於 [^0-9]。
例子:
a\Dc 可以用來匹配 "abc", "aGc", "a_c", "a c", "a#c", "a\nc" 等字串,但不能匹配 "a1c", "a5c" 等字串。
import re
bool(re.search('a\Dc', 'abc')) # True
bool(re.search('a\Dc', 'a5c')) # False
bool(re.search('a\Dc', 'a\nc')) # True
\s whitespace(小寫)
\s 用來匹配所有的空白字元 (whitespace) - 空白 (space)、tab 和換行符號 \r \n。
例子:
a\sc 可以用來匹配 "a c", "a\nc" 等字串,但不能匹配 "abc", "aGc", "a_c", "a#c", "a1c", "a5c" 等字串。
import re
bool(re.search('a\sc', 'a c')) # True
bool(re.search('a\sc', 'a5c')) # False
bool(re.search('a\sc', 'a\nc')) # True
\S not whitespace(大寫)
\S 用來匹配 \s 以外的所有字。
例子:
a\Sc 可以用來匹配 "abc", "aGc", "a_c", "a#c", "a1c", "a5c" 等字串,但不能匹配 "a c", "a\nc" 等字串。
import re
bool(re.search('a\Sc', 'a c')) # False
bool(re.search('a\Sc', 'a5c')) # True
bool(re.search('a\Sc', 'a\nc')) # False
[] character set
[ ] 中括號用來表示一個字元集合 (character set),整個中括號代表一個字元,裡面的內容就是這個字元的所有可能。
例子:
a[abcde123]c 可以用來匹配 "abc", "a1c" 等字串,但不能匹配 "aGc", "a_c", "a#c", "a5c", "a c", "a\nc" 等字串。
如果 [ ] 中有包含 ] 字元,你需要用反斜線 \ 來跳脫 (escape) 這一個特殊字元。
例子:
a[\]]c 可以用來匹配 "a]c" 字串。
import re
bool(re.search('a[abcde123]c', 'abc')) # True
bool(re.search('a[abcde123]c', 'a#c')) # False
bool(re.search('a[abcde123]c', 'a_c')) # False
[^ ] negated set
[^ ] 是 [ ] 的相反,用來匹配不在字元集合裡面的字元。
例子:
a[^abcde123]c 可以用來匹配 "aGc", "a_c", "a#c", "a5c", "a c", "a\nc" 等字串,但不能匹配 "abc", "a1c" 等字串。
import re
bool(re.search('a[^abcde123]c', 'abc')) # False
bool(re.search('a[^abcde123]c', 'a#c')) # True
bool(re.search('a[^abcde123]c', 'a_c')) # True
[A-Z] range
[ ] (或 [^ ]) 中還可以用 - 符號來表示連續 (range) 的好幾個字元。
例子:
a[a-zC-F3-7]c 其中 a-z 表示 a 到 z 所有的小寫英文字、C-F 表示大寫的 C 到 F (C D E F)、3-7 表示數字 3 到 7 (3 4 5 6 7),可以用來匹配 "abc", "a5c" 等字串,但不能匹配 "a1c", "aGc", "a_c", "a#c", "a c", "a\nc" 等字串。
import re
bool(re.search('a[a-zC-F3-7]c', 'abc')) # True
bool(re.search('a[a-zC-F3-7]c', 'a5c')) # True
bool(re.search('a[a-zC-F3-7]c', 'aGc')) # False
錨點符號 (anchor) 是用來表示「定位」的樣式,不用來比對字元,本身不佔據任何字元位置。
^… beginning
^ 用來表示只匹配以 … 「開頭」的字串。
例子:
^hello 可以用來匹配 "hello world" 字串,但不能匹配 "say hello 123",因為 hello 出現在 "hello world" 的開頭,但 "say hello 123" 的 hello 不在開頭。
但要特別注意在「多行」的字串中,像是:
101
hello Mike
^hello 無法用來匹配上面的字串,因為其 hello 不在開頭的位置!但你可以加上 m 修飾詞 (flag) 讓 ^ 改成匹配「行首」,例如 /^hello/m 即可用來匹配上面的字串。
import re
bool(re.search('^hello', 'hello world')) # True
bool(re.search('^hello', 'say hello 123')) # False
…$ end
$ 用來表示只匹配以 … 「結尾」的字串。
例子:
foo$ 可以用來匹配 "bar foo" 字串,但不能匹配 "foo bar",因為 foo 出現在 "bar foo" 的結尾,但 "foo bar" 的 foo 不在結尾。
但要特別注意在「多行」的字串中,像是:
123 foo
456
foo$ 無法用來匹配上面的字串,因為其 foo 不在結尾的位置!但你可以加上 m 修飾詞 (flag) 讓 $ 改成匹配「行尾」,例如 /foo$/m 即可用來匹配上面的字串。
import re
bool(re.search('foo$', 'bar foo')) # True
bool(re.search('foo$', 'foo bar')) # False
\b word boundary
\b 用來匹配單字邊界 (word boundary),表示字元的「前面」或「後面」除了空白字元 (whitespace)、標點符號 (punctuation) 或是在字串開頭或結尾外不可再有其它字元。
word boundary 可以看作是不屬於 \w 的字元。
例子:
llo\b 可以用來匹配 "hello world", "hello\nworld", "hello", "hello, Mike",但不能用來匹配 "hello_world", "helloworld", "hello101"。
\bworld\b 可以用來匹配 "hello world", "hello~world", "world",但不能用來匹配 "helloworld", "01world"。
import re
bool(re.search(r'llo\b', 'hello world')) # True
bool(re.search(r'llo\b', 'hello_world')) # False
\B not word boundary
\B 則是相對於 \b,用來匹配非單字邊界 (word boundary)。
例子:
llo\B 可以用來匹配 "hello_world", "helloworld", "hello101",但不能用來匹配 "hello world", "hello\nworld", "hello", "hello, Mike"。
\Bworld\B 可以用來匹配 "123worldxyz",但不能用來匹配 "helloworld", "hello world", "world"。
import re
bool(re.search(r'llo\B', 'hello world')) # False
bool(re.search(r'llo\B', 'hello_world')) # True
若字元為特殊符號,在 Regex 中具有其他意義,可以用反斜線的跳脫字符 \ 將特殊字元還原成其字面上的意思,換句話說跳脫字符可以將特殊符號的特殊意義去除!
例如使用 . 這時的 . 是代表真的點號,而不是 Regex 語法中的特殊意義;另外像是 + 也是代表加號,而不是指量詞。
特殊字元列表
Capturing Group ( )
在 Regex 的 pattern 中,用小括號 ( ) 圈住的部分表示一個子樣式 (subexpression),也稱作是一個群組 (group)。
( ) 有幾個用途:
import re
match = re.search(r'(hello \S+)', 'This is a hello world!')
print(match.group(1)) # hello world!
量詞 (quantifier) 表示某個條件需要出現的次數。
Plus +
+ 表示連續出現 1 次或多次。
例子:
pattern ab+c 可以用來匹配 "abc", "abbc", "abbbc", "abbbbbbc" 等字串,但 "ac", "adc" 不符合。
import re
match = re.search(r'a+', 'caaaaaaandy')
print(match.group()) # aaaaaaa
Star *
* 表示連續出現 0 次或多次。
例子:
pattern ab*c 可以用來匹配 "ac", "abc", "abbc", "abbbc", "abbbbbbc" 等字串,但 "adc", "a123" 不符合。
import re
match = re.search(r'bo*', 'A ghost booooed')
print(match.group()) # boooo
Quantifier {min,max} {n} {min,}
Quantifier 有三種寫法:
{min,max} 表示至少連續出現 min 次,但最多連續出現 max 次。
{n} 表示要出現 n 次。
{min,} 表示至少連續出現 min 次。
例子:
pattern ab{1,3}c 可以用來匹配 "abc", "abbc", "abbbc" 等字串,但 "ac", "abbbbbbc", "adc", "a123" 不符合。
pattern ab{3}c 可以用來匹配 "abbbc" 等字串,但 "ac", "abc", "abbc", "abbbbbbc", "adc", "a123" 不符合。
pattern ab{3,}c 可以用來匹配 "abbbc", "abbbbbbc" 等字串,但 "abc", "abbc", "ac", "adc", "a123" 不符合。
import re
match = re.search(r'a{1,3}', 'caaaaaaandy')
print(match.group()) # aaa
Optional ?
? 表示出現 0 次或 1 次。
例子:
pattern ab?c 可以用來匹配 "ac", "abc" 等字串,但 "abbc", "abbbc", "abbbbbbc", "adc", "a123" 不符合。
import re
match = re.search(r'e?le?', 'angel')
print(match.group()) # el
Lazy ?
對於指定的量詞,Regex 的匹配引擎在預設上,採能匹配越多字就盡量匹配,這一個特性叫做 greedy (貪婪)。
例如,用 pattern (.+)(\d+) 來匹配字串 "abcd1234",group 1 會得到 "abcd123",group 2 會得到 "4",正是因為 greedy 的特性讓 .+ 匹配到盡可能多的字。
? 還有另外一個用法,接在量詞後面 (+?, *?, {min,max}?, ??) 表示 lazy (非貪婪, 懶惰) 模式,會使 Regex 的匹配引擎變成以匹配越少字為原則,盡可能匹配短結果。
例如,用 pattern (.+?)(\d+) 來匹配字串 "abcd1234",group 1 會得到 "abcd",group 2 會得到 "1234",正是因為 lazy 的特性讓 .+ 匹配到盡可能少的字。
import re
match = re.search(r'<.+?>', '<em>Hello World</em>')
print(match.group()) # <em>
pat = '[a-zA-Z]+'
text = 'Hello, hm...this is Tom speaking, who are you?'
re.findall(pat, text)
# result
['Hello', 'hm', 'this', 'is', 'Tom', 'speaking', 'who', 'are', 'you']
re.match('h', 'hello')
# result
<re.Match object; span=(0, 1), match='h'>
re.search('e', 'hello')
# result
<re.Match object; span=(1, 2), match='e'>
text = 'one, two...ten')
re.split('[,. ]+', text)
# result
['one', 'two', 'three']
# use 'maxsplit'
re.split('[,. ]+', text, maxsplit=1)
# result
['one', 'two...ten']
/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/
/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/
/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
/^<([a-z]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)$/