正則表達(dá)式(regular expression)描述了一種字符串匹配的模式(pattern),可以用來檢查一個串是否含有某種子串、將匹配的子串替換或者從某個串中取出符合某個條件的子串等。就好比用模具做產(chǎn)品,而正則就是這個模具,定義一種規(guī)則去匹配符合規(guī)則的字符。
一、正則表達(dá)式語法
1.1 元字符
特殊字符:\.^$?+*{}[]()| 以上特殊字符要想使用字面值,必須使用"\"進(jìn)行轉(zhuǎn)義.
字符類
表示方法 | 意思 | 舉例 |
---|---|---|
\b | 不會消耗任何字符只匹配一個位置,常用于匹配單詞邊界。 | 例如我想從字符串中"This is Regex"匹配單獨的單詞 "is" 正則就要寫成 "\bis\b" ,\b 不會匹配is 兩邊的字符,但它會識別is 兩邊是否為單詞的邊界 。 |
\d | 匹配數(shù)字。 | 例如要匹配一個固定格式的電話號碼以0開頭前4位后7位,如0737-5686123 正則:^0\d\d\d-\d\d\d\d\d\d\d$ 這里只是為了介紹"\d"字符。 |
\w | 匹配字母,數(shù)字,下劃線。 | 例如我要匹配"a2345BCD__TTz" 正則:"\w+" 這里的"+"字符為一個量詞指重復(fù)的次數(shù),稍后會詳細(xì)介紹。 |
\s | 匹配空格 。 | 例如字符 "a b c" 正則:"\w\s\w\s\w" 一個字符后跟一個空格,如有字符間有多個空格直接把"\s" 寫成 "\s+" 讓空格重復(fù)。 |
. | 匹配除了換行符以外的任何字符。 | 這個算是"\w"的加強(qiáng)版了"\w"不能匹配 空格 如果把字符串加上空格用"\w"就受限了,看下用 "."是如何匹配字符"a23 4 5 B C D__TTz" 正則:".+"。 |
[abc] | 字符組 匹配包含括號內(nèi)元素的字符 。 | 這個比較簡單了只匹配括號內(nèi)存在的字符,還可以寫成[a-z]匹配a至z的所以字母就等于可以用來控制只能輸入英文了, |
- 幾種反義
寫法很簡單改成大寫就行了,意思與原來的相反,這里就不舉例子了
表示方法 | 意思 |
---|---|
\W | 匹配任意不是字母,數(shù)字,下劃線 的字符 |
\S | 匹配任意不是空白符的字符 |
\D | 匹配任意非數(shù)字的字符 |
\B | 匹配不是單詞開頭或結(jié)束的位置 |
[^abc] | 匹配除了abc以外的任意字符 |
1.2 量詞
表示方法 | 意思 |
---|---|
? | 匹配前面的字符0次或1次 |
* | 匹配前面的字符0次或多次 |
+ | 匹配前面的字符1次或者多次 |
{m} | 匹配前面表達(dá)式m次 |
{m,} | 匹配前面表達(dá)式至少m次 |
{,n} | 匹配前面的正則表達(dá)式最多n次 |
{m,n} | 匹配前面的正則表達(dá)式至少m次,最多n次 |
注意點:以上量詞都是貪婪模式,會盡可能多的匹配。
此外,還需要介紹兩個概念::
貪婪(貪心)。貪婪量詞會盡可能匹配更多的字符,例如對于字符串“AAAAAAAAAAA”,如使用“A*”匹配則會得到整個字符串。貪婪量詞會首先匹配整個字符串,嘗試匹配時,它會選定盡可能多的內(nèi)容,如果 失敗則回退一個字符,然后再次嘗試回退的過程就叫做回溯,它會每次回退一個字符,直到找到匹配的內(nèi)容或者沒有字符可以回退。
懶惰(勉強(qiáng)) 。懶惰量詞會盡可能少的匹配字符,同樣例如對于字符串“AAAAAAAAAAA”,如使用懶惰“A*?”匹配則只得到“A”。懶惰量詞使用另一種方式匹配,它從目標(biāo)的起始位置開始嘗試匹配,每次檢查一個字符,并尋找它要匹配的內(nèi)容,如此循環(huán)直到字符結(jié)尾處。
如果要將貪婪量詞改為懶惰量詞,通過在量詞后面跟隨一個?來實現(xiàn)。
表示方法 | 意思 | 舉例 |
---|---|---|
*? | 重復(fù)任意次,但盡可能少重復(fù)。 | 如 "acbacb" 正則 "a.*?b" 只會取到第一個"acb" 原本可以全部取到但加了限定符后,只會匹配盡可能少的字符 ,而"acbacb"最少字符的結(jié)果就是"acb" 。 |
+? | 重復(fù)1次或更多次,但盡可能少重復(fù)。 | 與上面一樣,只是至少要重復(fù)1次。 |
?? | 重復(fù)0次或1次,但盡可能少重復(fù)。 | 如 "aaacb" 正則 "a.??b" 只會取到最后的三個字符"acb"。 |
{n,m}? | 重復(fù)n到m次,但盡可能少重復(fù)。 | 如 "aaaaaaaa" 正則 "a{0,m}" 因為最少是0次所以取到結(jié)果為空。 |
{n,}? | 重復(fù)n次以上,但盡可能少重復(fù)。 | 如 "aaaaaaa" 正則 "a{1,}" 最少是1次所以取到結(jié)果為 "a"。 |
二、正則進(jìn)階
2.1組與捕獲
正則中的捕獲分組,其實就是一個括號內(nèi)的內(nèi)容 如 "(\d)\d" 而"(\d)" 這就是一個捕獲分組。 每一個沒有使用?:的小括號都會分配一個組好,從1開始,從左到右遞增,可以通過\i引用前面()內(nèi)表達(dá)式捕獲的內(nèi)容。如(\d)\d\1 這里的"\1"就是對"(\d)"的后向引用。
分組的另一個作用就是將正則表達(dá)式的一部分內(nèi)容進(jìn)行組合,以便使用量詞或者|。
下面列出捕獲分組常有的用法:
表示方法 | 意思 |
---|---|
(exp) | 匹配exp,并捕獲文本到自動命名的組里。 |
(?<name>exp) | 匹配exp,并捕獲文本到名稱為name的組里。 |
(?:exp) | 匹配exp,不捕獲匹配的文本,也不給此分組分配組號。 |
引用方法:
- 通過組號反向引用: 每一個沒有使用?:的小括號都會分配一個組好,從1開始,從左到右遞增,可以通過\i引用前面()內(nèi)表達(dá)式捕獲的內(nèi)容
- 通過組名反向引用前面小括號內(nèi)捕獲的內(nèi)容:可以通過在左括號后面跟隨?P<name>,尖括號中放入組名來為一個組起一個別名,后面通過(?P=name)來引用 前面捕獲的內(nèi)容。如(? P<word>\w+)\s+(?P=word)來匹配重復(fù)的單詞。
注意點:反向引用不能放在字符類[]中使用。
2.2零寬斷言
零寬斷言正如它的名字一樣,是一種零寬度的匹配,它匹配到的內(nèi)容不會保存到匹配結(jié)果中去,最終匹配結(jié)果只是一個位置而已。作用是給指定位置添加一個限定條件,用來規(guī)定此位置之前或者之后的字符必須滿足限定條件才能使正則中的字表達(dá)式匹配成功。
常用斷言:
表示方法 | 意思 |
---|---|
^ | 在起始處匹配,如果有MULTILINE標(biāo)志,則在每個換行符后匹配 |
$ | 在結(jié)尾處匹配,如果有MULTILINE標(biāo)志,則在每個換行符前匹配 |
\b | 匹配單詞的邊界,放在字符類[]中則表示backspace |
\B | 匹配非單詞邊界,受ASCII標(biāo)記影響 |
\A | 在起始處匹配 |
\Z | 在結(jié)尾處匹配 |
(?=exp) | 零寬度正預(yù)測先行斷言,它斷言自身出現(xiàn)的位置的后面能匹配表達(dá)式exp。 |
(?<=exp) | 零寬度正回顧后發(fā)斷言,它斷言自身出現(xiàn)的位置的前面能匹配表達(dá)式exp |
(?!exp) | 零寬度負(fù)預(yù)測先行斷言,斷言此位置的后面不能匹配表達(dá)式exp。 |
(?<!exp) | 零寬度負(fù)回顧后發(fā)斷言來斷言此位置的前面不能匹配表達(dá)式exp |
例如:我們要查找hello,但是hello后面必須是world,正則表達(dá)式可以這樣寫:"(hello)\s+(?=world)",用來匹配"hello wangxing"和"hello world"只能匹配到后者的hello
2.3選擇匹配
可使用“|”進(jìn)行表示選擇,A|B可以匹配A或B。例如(P|p)ython可以匹配'Python'或者'python'。