1. 模式匹配與正則表達(dá)式
你可能熟悉文本查找,即按下Ctrl-F,輸入你要查找的詞。 “正則表達(dá)式”更進(jìn)一步,它們讓你指定要查找的“模式”。 你也許不知道一家公司的準(zhǔn)確電話(huà)號(hào)碼,但如果你住在美國(guó)或加拿大, 你就知道它有3位數(shù)字,然后是一個(gè)短橫線(xiàn),然后是4位數(shù)字(有時(shí)候以3位區(qū)號(hào)開(kāi)始)。 因此作為一個(gè)人,你看到一個(gè)電話(huà)號(hào)碼就知道: 415-555-1234 是電話(huà)號(hào)碼,但 4,155,551,234 不是。
正則表達(dá)式很有用,但如果不是程序員,很少會(huì)有人了解它, 盡管大多數(shù)現(xiàn)代文本編輯器和文字處理器(諸如微軟的Word或OpenOffice/LibreOffcie), 都有查找和查找替換功能,可以根據(jù)正則表達(dá)式查找。 正則表達(dá)式可以節(jié)約大量時(shí)間,不僅適用于軟件用戶(hù),也適用于程序員。 實(shí)際上,技術(shù)作家Cory Doctorow聲稱(chēng),甚至應(yīng)該在教授編程之前,先教授正則表達(dá)式:
“知道[正則表達(dá)式]可能意味著用3步解決一個(gè)問(wèn)題, 而不是用3000步。如果你是一個(gè)技術(shù)怪俠, 別忘了你用幾次擊鍵就能解決的問(wèn)題, 其他人需要數(shù)天的煩瑣工作才能解決, 而且他們?nèi)菀追稿e(cuò)。”
在本章中,你將從編寫(xiě)一個(gè)程序開(kāi)始,先不用正則表達(dá)式來(lái)尋找文本模式。 然后再看看,使用正則表達(dá)式讓代碼變得多么簡(jiǎn)潔。 我將展示用正則表達(dá)式進(jìn)行基本匹配,然后轉(zhuǎn)向一些更強(qiáng)大的功能,諸如字符串替換, 以及創(chuàng)建你自己的字符類(lèi)型。
1.1. 不用正則表達(dá)式來(lái)查找文本模式
假設(shè)你希望在字符串中查找電話(huà)號(hào)碼。你知道模式:3個(gè)數(shù)字, 一個(gè)短橫線(xiàn),3個(gè)數(shù)字,一個(gè)短橫線(xiàn),再是4個(gè)數(shù)字。 例如:415-555-4242。
假定我們用一個(gè)名為 isPhoneNumber() 的函數(shù), 來(lái)檢查字符串是否匹配模式,它返回 True 或 False 。 打開(kāi)一個(gè)新的文件編輯器窗口,輸入以下代碼, 然后保存為 isPhoneNumber.py :
def isPhoneNumber(text):
if len(text) !=12:
return False
for i in range(3):
if not text[i].isdecimal():
return False
if text[3]!=‘-’:
return False
for i in range(4,7):
if not text[i].isdecimal():
return False
if text[7] != ‘-’:
return False
for i in range(8,12):
if not text[i].isdecimal():
return False
return True
print(‘415-555-4242 is a phone number:’)
print(isPhoneNumber(‘415-555-4242’))
print(‘Moshi moshi is a phone number:’)
print(isPhoneNumber(‘Moshi moshi’))
415-555-4242 is a phone number:
True
Moshi moshi is a phone number:
False
isPhoneNumber() 函數(shù)的代碼進(jìn)行幾項(xiàng)檢查, 看看 text 中的字符串是不是有效的電話(huà)號(hào)碼。 如果其中任意一項(xiàng)檢查失敗,函數(shù)就返回 False 。 代碼首先檢查該字符串是否剛好有12個(gè)字符。 然后它檢查區(qū)號(hào)(就是 text 中的前3個(gè)字符)是否只包含 數(shù)字。函數(shù)剩下的部分檢查該字符串是否符合電話(huà)號(hào)碼的模式: 號(hào)碼必須在區(qū)號(hào)后出現(xiàn)第一個(gè)短橫線(xiàn)), 3個(gè)數(shù)字,然后是另一個(gè)短橫線(xiàn),最后是4個(gè)數(shù)字。 如果程序執(zhí)行通過(guò)了所有的檢查,它就返回 True 。
用參數(shù) ‘415-555-4242’ 調(diào)用 isPhoneNumber() 將返回真。 用參數(shù) ‘Moshimoshi’ 調(diào)用 isPhoneNumber() 將返回假, 第一項(xiàng)測(cè)試失敗了,因?yàn)椴皇?2個(gè)字符。
必須添加更多代碼,才能在更長(zhǎng)的字符串中尋找這種文本模式。 用下面的代碼, 替代 isPhoneNumber.py 中最后4個(gè) print() 函數(shù)調(diào)用:
message=‘Call me at 415-555-1011 tomorrow.415-555-9999 is my office.’
for i in range(len(message)):
chunk=message[i:i+12]
if isPhoneNumber(chunk):
print(‘Phone number found:’ + chunk)
print(‘Done’)
Phone number found:415-555-1011
Phone number found:415-555-9999
Done
該程序運(yùn)行時(shí),輸出看起來(lái)像這樣:
在 for 循環(huán)的每一次迭代中, 取自 message 的一段新的12個(gè)字符被賦給變量 chunk() 。 例如,在第一次迭代, i 是 0 , chunk 被賦值為 message[0:12] (即字符串’Call me at 4’)。在下一次迭代, i 是1, chunk 被賦值為 message[1:13] (字符串 ‘a(chǎn)ll me at 41’ )。
將 chunk 傳遞給 isPhoneNumber(), 看看它是否符合電話(huà)號(hào)碼的模式。如果符合, 就打印出這段文本。
繼續(xù)遍歷 message ,最終 chunk 中的12個(gè)字符會(huì)是一個(gè)電話(huà)號(hào)碼。 該循環(huán)遍歷了整個(gè)字符串,測(cè)試了每一段12個(gè)字符, 打印出所有滿(mǎn)足 isPhoneNumber() 的 chunk 。 當(dāng)我們遍歷完 message ,就打印出 Done 。
在這個(gè)例子中,雖然 message 中的字符串很短, 但它也可能包含上百萬(wàn)個(gè)字符,程序運(yùn)行仍然不需要一秒鐘。 使用正則表達(dá)式查找電話(huà)號(hào)碼的類(lèi)似程序, 運(yùn)行也不會(huì)超過(guò)一秒鐘,但用正則表達(dá)式編寫(xiě)這類(lèi)程序會(huì)快得多。
1.2. 用正則表達(dá)式查找文本模式
如果你想在有分機(jī)的電話(huà)號(hào)碼中快速查找電話(huà)號(hào),例如415-555-4242 x99,該怎么辦呢?
正則表達(dá)式,又稱(chēng)規(guī)則表達(dá)式,英語(yǔ)簡(jiǎn)稱(chēng)為 regex,是文本模式的描述方法,能幫助你方便的檢查一個(gè)字符串是否與某種模式匹配。
例如,\d 是一個(gè)正則表達(dá)式,表示一位數(shù)字字符, 即任何一位0到9的數(shù)字。 Python 使用正則表達(dá)式 \d\d\d-\d\d\d-\d\d\d\d , 來(lái)匹配前面 isPhoneNumber()函數(shù)匹配的同樣文本: 3個(gè)數(shù)字、一個(gè)短橫線(xiàn)、3個(gè)數(shù)字、一個(gè)短橫線(xiàn)、4個(gè)數(shù)字。 所有其他字符串都不能匹配 \d\d\d-\d\d\d-\d\d\d\d 正則表達(dá)式。
但正則表達(dá)式可以復(fù)雜得多。例如, 在一個(gè)模式后加上花括號(hào)包圍的3 ({3}), 就是說(shuō),“匹配這個(gè)模式3次”。 所以較短的正則表達(dá)式 \d{3}-\d{3}-\d{4} , 也匹配正確的電話(huà)號(hào)碼格式。
1.2.1. 創(chuàng)建正則表達(dá)式對(duì)象
Python 中所有正則表達(dá)式的函數(shù)都在 re 模塊中。在交互式環(huán)境中輸入以下代碼,導(dǎo)入該模塊:
import re
re 模塊的 compile() 函數(shù)根據(jù)一個(gè)模式字符串和可選的標(biāo)志參數(shù)生成一個(gè)正則表達(dá)式對(duì)象。 該對(duì)象擁有一系列方法用于正則表達(dá)式匹配和替換。 例如,向 re.compile() 傳入一個(gè)字符串值表示正則表達(dá)式, 它將返回一個(gè) Regex 模式對(duì)象(簡(jiǎn)稱(chēng)為 Regex 對(duì)象)。
要?jiǎng)?chuàng)建一個(gè) Regex 對(duì)象來(lái)匹配電話(huà)號(hào)碼模式, 就在交互式環(huán)境中輸入以下代碼。
regobj = re.compile(‘\d\d\d-\d\d\d-\d\d\d\d’)
現(xiàn)在 regobj 變量包含了一個(gè) Regex 對(duì)象。
1.2.2. 匹配 Regex 對(duì)象
Regex 對(duì)象的 search() 方法查找傳入的字符串,尋找該正則表達(dá)式的所有匹配。 如果字符串中沒(méi)有找到該正則表達(dá)式模式,search() 方法將返回None 。 如果找到了該模式,search() 方法將返回一個(gè) Match 對(duì)象。 Match 對(duì)象有一個(gè) group() 方法,它返回被查找字符串中實(shí)際匹配的文本。 例如,在交互式環(huán)境中輸入以下代碼:
mo = regobj.search(‘My number is 415-555-4242.’)
print('Phone number found: ’ + mo.group())
Phone number found: 415-555-4242
變量名 mo 是一個(gè)通用的名稱(chēng),用于 Match 對(duì)象。
這里,我們將期待的模式傳遞給 re.compile() ,并將得到的 Regex 對(duì)象保存在 phoneNumRegex 中。 然后我們?cè)?phoneNumRegex 上調(diào)用 search() ,向它傳入想查找的字符串。查找的結(jié)果保存在變量 mo 中。 在這個(gè)例子里,我們知道模式會(huì)在這個(gè)字符串中找到,所以我們知道會(huì)返回一個(gè) Match 對(duì)象。 知道 mo 包含一個(gè) Match 對(duì)象,而不是空值 None ,我們就可以在 mo 變量上調(diào)用 group() ,返回匹配的結(jié)果。 將 mo.group() 寫(xiě)在打印語(yǔ)句中,顯示出完整的匹配,即 415-555-4242 。
如果對(duì)象沒(méi)找到,可以進(jìn)行判斷:
mo2 = regobj.search(‘my number is 41555433.’)
print(‘got’) if mo2 else print(‘not got’)
not got
向 re.compile() 傳遞原始字符串
回憶一下, Python 中轉(zhuǎn)義字符使用倒斜杠()。 字符串 V 表示一個(gè)換行字符, 而不是倒斜杠加上一個(gè)小寫(xiě)的 n 。 你需要輸入轉(zhuǎn)義字符 \ ,才能打印出一個(gè)倒斜杠。 所以 ‘\n’ 表示一個(gè)倒斜杠加上一個(gè)小寫(xiě)的 n 。 但是,通過(guò)在字符串的第一個(gè)引號(hào)之前加上 r , 可以將該字符串標(biāo)記為原始字符串,它不包括轉(zhuǎn)義字符。
因?yàn)檎齽t表達(dá)式常常使用倒斜杠, 向 re.compile() 函數(shù)傳入原始字符串就很方便, 而不是輸入額外得到斜杠。輸入 r’\d\d\d-\d\d\d-\d\d\d\d’ , 比輸入 ‘\d\d\d-\d\d\d-\d\d\d\d’ 要容易得多。
1.2.3. 正則表達(dá)式匹配復(fù)習(xí)
雖然在 Python中使用正則表達(dá)式有幾個(gè)步驟, 但每一步都相當(dāng)簡(jiǎn)單。
用 import re 導(dǎo)入正則表達(dá)式模塊。
用 re.compile() 函數(shù)創(chuàng)建一個(gè) Regex 對(duì)象(記得使用原始字符串)。
向 Regex 對(duì)象的 search() 方法傳入想查找的字符串。它返回一個(gè) Match 對(duì)象。
調(diào)用 Match 對(duì)象的 group() 方法,返回實(shí)際匹配文本的字符串。
下面主要介紹Python中常用的正則表達(dá)式處理函數(shù)。
1.2.4. re.match函數(shù)
re.match() 嘗試從字符串的起始位置匹配一個(gè)模式,如果不是起始位置匹配成功的話(huà), match() 就返回 None 。
函數(shù)語(yǔ)法:
re.match(pattern, string, flags=0)
函數(shù)參數(shù)說(shuō)明:
pattern 匹配的正則表達(dá)式
string 要匹配的字符串。
flags 標(biāo)志位,用于控制正則表達(dá)式的匹配方式,如:是否區(qū)分大小寫(xiě),多行匹配等等。
我們可以使用 group(num) 或 groups() 匹配對(duì)象函數(shù)來(lái)獲取匹配表達(dá)式。
group(num=0) 匹配的整個(gè)表達(dá)式的字符串, group() 可以一次輸入多個(gè)組號(hào),在這種情況下它將返回一個(gè)包含那些組所對(duì)應(yīng)值的元組。
groups() 返回一個(gè)包含所有小組字符串的元組,從 1 到 所含的小組號(hào)。
實(shí)例 1:
在起始位置匹配
print(re.match(‘www’, ‘www.runoob.com’).span())
(0, 3)
不在起始位置匹配
print(re.match(‘com’, ‘www.runoob.com’))
None
1.2.5. re.search方法
re.search 掃描整個(gè)字符串并返回第一個(gè)成功的匹配。
函數(shù)語(yǔ)法:
re.search(pattern, string, flags=0)
函數(shù)參數(shù)說(shuō)明:
參數(shù) | 描述
pattern | 匹配的正則表達(dá)式
string | 要匹配的字符串。
flags | 標(biāo)志位,用于控制正則表達(dá)式的匹配方式,如:是否區(qū)分大小寫(xiě),多行匹配等等。
匹配成功 re.search 方法返回一個(gè)匹配的對(duì)象,否則返回None。
我們可以使用 group(num) 或 groups() 匹配對(duì)象函數(shù)來(lái)獲取匹配表達(dá)式。
匹配對(duì)象方法 | 描述
group(num=0) |匹配的整個(gè)表達(dá)式的字符串,group() 可以一次輸入多個(gè)組號(hào),在這種情況下它將返回一個(gè)包含那些組所對(duì)應(yīng)值的元組。
groups() | 返回一個(gè)包含所有小組字符串的元組,從 1 到 所含的小組號(hào)。
實(shí)例 1:
在起始位置匹配
print(re.search(‘www’, ‘www.runoob.com’).span())
(0, 3)
不在起始位置匹配
print(re.search(‘com’, ‘www.runoob.com’).span())
(11, 14)
實(shí)例 2:
import re
line = “Cats are smarter than dogs”;
searchObj = re.search(‘(.) are (.?) .*’, line, re.M|re.I)
if searchObj:
print ("searchObj.group() : ", searchObj.group())
print ("searchObj.group(1) : ", searchObj.group(1))
print ("searchObj.group(2) : ", searchObj.group(2))
else:
print (“Nothing found!!”)
searchObj.group() : Cats are smarter than dogs
searchObj.group(1) : Cats
searchObj.group(2) : smarter
instr = ‘/home/bk/book-rst/doculet/sphinx-tutorial/runoob-src/pt01_language_eb00kh’
re_book = re.compile(‘eb\d\d…’)
uu = re_book.search(instr)
uu.span()
(67, 73)
dir(uu)
[‘class’,
‘class_getitem’,
‘copy’,
‘deepcopy’,
‘delattr’,
‘dir’,
‘doc’,
‘eq’,
‘format’,
‘ge’,
‘getattribute’,
‘getitem’,
‘getstate’,
‘gt’,
‘hash’,
‘init’,
‘init_subclass’,
‘le’,
‘lt’,
‘module’,
‘ne’,
‘new’,
‘reduce’,
‘reduce_ex’,
‘repr’,
‘setattr’,
‘sizeof’,
‘str’,
‘subclasshook’,
‘end’,
‘endpos’,
‘expand’,
‘group’,
‘groupdict’,
‘groups’,
‘lastgroup’,
‘lastindex’,
‘pos’,
‘re’,
‘regs’,
‘span’,
‘start’,
‘string’]
uu.group()
‘eb00kh’
1.2.6. re.match 與 re.search 的區(qū)別
re.match 只匹配字符串的開(kāi)始,如果字符串開(kāi)始不符合正則表達(dá)式,則匹配失敗,函數(shù)返回 None ; 而 re.search 匹配整個(gè)字符串,直到找到一個(gè)匹配。
實(shí)例:
import re
line = “Cats are smarter than dogs”;
matchObj = re.match( ‘dogs’, line, re.M|re.I)
if matchObj:
print ("match --> matchObj.group() : ", matchObj.group())
else:
print (“No match!!”)
matchObj = re.search( r’dogs’, line, re.M|re.I)
if matchObj:
print ("search --> matchObj.group() : ", matchObj.group())
else:
print (“No match!!”)
No match!!
search --> matchObj.group() : dogs
1.2.7. 檢索和替換
Python 的re模塊提供了re.sub用于替換字符串中的匹配項(xiàng)。
語(yǔ)法:
re.sub(pattern, repl, string, count=0)
參數(shù):
pattern : 正則中的模式字符串。
repl : 替換的字符串,也可為一個(gè)函數(shù)。
string : 要被查找替換的原始字符串。
count : 模式匹配后替換的最大次數(shù),默認(rèn) 0 表示替換所有的匹配。
實(shí)例:
#!/usr/bin/python3
import re
phone = “2004-959-559 # 這是一個(gè)電話(huà)號(hào)碼”
刪除注釋
num = re.sub(‘#.*$’, “”, phone)
print ("電話(huà)號(hào)碼 : ", num)
移除非數(shù)字的內(nèi)容
num = re.sub(‘\D’, “”, phone)
print ("電話(huà)號(hào)碼 : ", num)
電話(huà)號(hào)碼 : 2004-959-559
電話(huà)號(hào)碼 : 2004959559
1.2.8. repl 參數(shù)是一個(gè)函數(shù)
以下實(shí)例中將字符串中的匹配的數(shù)字乘于 2:
#!/usr/bin/python
import re
將匹配的數(shù)字乘于 2
def double(matched):
value = int(matched.group(‘value’))
return str(value * 2)
s = ‘A23G4HFD567’
print(re.sub(‘(?P\d+)’, double, s))
A46G8HFD1134
1.2.9. 正則表達(dá)式修飾符 - 可選標(biāo)志
正則表達(dá)式可以包含一些可選標(biāo)志修飾符來(lái)控制匹配的模式。修飾符被指定為一個(gè)可選的標(biāo)志。多個(gè)標(biāo)志可以通過(guò)按位 OR(|) 它們來(lái)指定。如 re.I | re.M 被設(shè)置成 I 和 M 標(biāo)志:
修飾符 | 描述
re.I 使匹配對(duì)大小寫(xiě)不敏感
re.L 做本地化識(shí)別(locale-aware)匹配
re.M 多行匹配,影響 ^ 和 $
re.S 使 . 匹配包括換行在內(nèi)的所有字符
re.U 根據(jù)Unicode字符集解析字符。這個(gè)標(biāo)志影響 \w , \W , \b , \B .
re.X 該標(biāo)志通過(guò)給予你更靈活的格式以便你將正則表達(dá)式寫(xiě)得更易于理解。
1.2.10. 正則表達(dá)式模式
模式字符串使用特殊的語(yǔ)法來(lái)表示一個(gè)正則表達(dá)式:
字母和數(shù)字表示他們自身。一個(gè)正則表達(dá)式模式中的字母和數(shù)字匹配同樣的字符串。
多數(shù)字母和數(shù)字前加一個(gè)反斜杠時(shí)會(huì)擁有不同的含義。
標(biāo)點(diǎn)符號(hào)只有被轉(zhuǎn)義時(shí)才匹配自身,否則它們表示特殊的含義。
反斜杠本身需要使用反斜杠轉(zhuǎn)義。
由于正則表達(dá)式通常都包含反斜杠,所以你最好使用原始字符串來(lái)表示它們。 模式元素(如 r’/t’ ,等價(jià)于’//t’ )匹配相應(yīng)的特殊字符。
下表列出了正則表達(dá)式模式語(yǔ)法中的特殊元素。如果你使用模式的同時(shí)提供了可選的標(biāo)志參數(shù),某些模式元素的含義會(huì)改變。
模式 | 描述
^ 匹配字符串的開(kāi)頭
$ 匹配字符串的末尾。
. 匹配任意字符,除了換行符,當(dāng)re.DOTALL標(biāo)記被指定時(shí),則可以匹配包括換行符的任意字符。
[…] 用來(lái)表示一組字符,單獨(dú)列出: [amk] 匹配 ‘a(chǎn)’,‘m’或’k’
[^…] 不在[]中的字符: [^abc] 匹配除了a,b,c之外的字符。
re* 匹配0個(gè)或多個(gè)的表達(dá)式。
re+ 匹配1個(gè)或多個(gè)的表達(dá)式。
re? 匹配0個(gè)或1個(gè)由前面的正則表達(dá)式定義的片段,非貪婪方式
re{ n}
re{ n,} 精確匹配n個(gè)前面表達(dá)式。
re{ n, m} 匹配 n 到 m 次由前面的正則表達(dá)式定義的片段,貪婪方式
a|b 匹配a或b
(re) G匹配括號(hào)內(nèi)的表達(dá)式,也表示一個(gè)組
(?imx) 正則表達(dá)式包含三種可選標(biāo)志:i, m, 或 x 。只影響括號(hào)中的區(qū)域。
(?-imx) 正則表達(dá)式關(guān)閉 i, m, 或 x 可選標(biāo)志。只影響括號(hào)中的區(qū)域。
(?: re) 類(lèi)似 (…), 但是不表示一個(gè)組
(?imx:re) 在括號(hào)中使用i, m, 或 x 可選標(biāo)志
(?-imx: re) 在括號(hào)中不使用i, m, 或 x 可選標(biāo)志
(?#…) 注釋.
(?= re) 前向肯定界定符。如果所含正則表達(dá)式,以 … 表示,在當(dāng)前位置成功匹配時(shí)成功,否則失敗。但一旦所含表達(dá)式已經(jīng)嘗試,匹配引擎根本沒(méi)有提高;模式的剩余部分還要嘗試界定符的右邊。
(?! re) 前向否定界定符。與肯定界定符相反;當(dāng)所含表達(dá)式不能在字符串當(dāng)前位置匹配時(shí)成功
(?> re) 匹配的獨(dú)立模式,省去回溯。
\w 匹配字母數(shù)字
\W 匹配非字母數(shù)字
\s 匹配任意空白字符,等價(jià)于 [\t\n\r\f] .
\S 匹配任意非空字符
\d 匹配任意數(shù)字,等價(jià)于 [0-9] .
\D 匹配任意非數(shù)字
\A 匹配字符串開(kāi)始
\Z 匹配字符串結(jié)束,如果是存在換行,只匹配到換行前的結(jié)束字符串。c
\z 匹配字符串結(jié)束
\G 匹配最后匹配完成的位置。
\b 匹配一個(gè)單詞邊界,也就是指單詞和空格間的位置。例如, er\b 可以匹配 never 中的 er , 但不能匹配 verb 中的 er 。
\B 匹配非單詞邊界。‘er:raw-latex:B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。
\n, \t , 等. 匹配一個(gè)換行符。匹配一個(gè)制表符。等
\1…\9 匹配第n個(gè)分組的內(nèi)容。
\10 匹配第n個(gè)分組的內(nèi)容,如果它經(jīng)匹配。否則指的是八進(jìn)制字符碼的表達(dá)式。
正則表達(dá)式符號(hào)復(fù)習(xí)
本章介紹了許多表示法,所以這里快速?gòu)?fù)習(xí)一下學(xué)到的內(nèi)容:
? 匹配零次或一次前面的分組。
匹配零次或多次前面的分組。
+匹配一次或多次前面的分組。
{n}匹配 n 次前面的分組。
{n,} 匹配 n 次或更多前面的分組。
{,m} 匹配零次到 m 次前面的分組。
{n,m}匹配至少 n 次、至多 m 次前面的分組。
{n,m}? 或 *? 或 +? 對(duì)前面的分組進(jìn)行非貪心匹配。
^spam 意味著字符串必須以 spam 開(kāi)始。
spam$意味著字符串必須以 spam 結(jié)束。
.匹配所有字符,換行符除外。
\d 、 \w和\s 分別匹配數(shù)字、單詞和空格。
\D、\W和 \S分別匹配出數(shù)字、單詞和空格外的所有字符。
[abc] 匹配方括號(hào)內(nèi)的任意字符(諸如a、b或c)。
[^abc] 匹配不在方括號(hào)內(nèi)的任意字符。