正则表达式里转义字符_五分钟搞定正则表达式,如果没搞定,再加两分钟
五分鐘搞定正則表達(dá)式,如果沒(méi)搞定,再加兩分鐘
【這是 ZY 第 18 篇原創(chuàng)文章】
文章概覽
一、正則表達(dá)式介紹
正則表達(dá)式,又稱規(guī)則表達(dá)式。(英語(yǔ):Regular Expression,在代碼中常簡(jiǎn)寫為regex、regexp或RE),計(jì)算機(jī)科學(xué)的一個(gè)概念。正則表達(dá)式通常被用來(lái)檢索、替換那些符合某個(gè)模式(規(guī)則)的文本。不用過(guò)多介紹,大家對(duì)正則表達(dá)式應(yīng)該不太陌生。即使沒(méi)有用過(guò),也一定聽說(shuō)過(guò)。
我們先看幾個(gè)常見(jiàn)的正則表達(dá)式:
對(duì)于正則表達(dá)式,第一映像是一串神秘的字符串。如果不是真正了解其規(guī)則,看到這字符串,定然是摸不著頭腦。
不過(guò)說(shuō)實(shí)話,了解其規(guī)則以后,看到這數(shù)字,也有點(diǎn)頭疼。畢竟正則這個(gè)東西,寫時(shí)爽歪歪,看時(shí)如天書。
話雖這樣說(shuō),正則表達(dá)式說(shuō)白了,也就是一連串的規(guī)則而已,只要了解了規(guī)則,一點(diǎn)一點(diǎn)總能看懂。所以不要有畏難情緒。
我們從最簡(jiǎn)單的例子開始,一點(diǎn)一點(diǎn)添加規(guī)則,爭(zhēng)取讓大家在學(xué)會(huì)正則表達(dá)式的過(guò)程中感覺(jué)不到絲毫痛苦。
(這里有一個(gè)網(wǎng)站,http://tool.oschina.net/regex/#,可以在線測(cè)試正則表達(dá)式的正確性,讀者朋友們可以在這上面進(jìn)行測(cè)試,方便學(xué)習(xí),我們后面的例子講解,也用這個(gè)工具)。
二、幾個(gè)常用規(guī)則
前面看了那么復(fù)雜的例子,我們這里回歸本源,從一個(gè)簡(jiǎn)單的例子開始看。
2.1 完全匹配
正則表達(dá)式是用來(lái)匹配文本的,現(xiàn)在假設(shè)我們要匹配 "abcdefg" 這一字符串中的 "abc" 三個(gè)字母,我們?cè)撛趺磳懩?#xff1f;
abc對(duì),不要懷疑,就是這么簡(jiǎn)單。
如果想匹配 "def",那么就是
是不是很簡(jiǎn)單呢?是不是小腦瓜中又透露出一絲疑惑?
如果正則表達(dá)式的匹配內(nèi)容很簡(jiǎn)單,也很明確,可以進(jìn)行完全匹配,寫出來(lái)的結(jié)果就是這樣的。
2.2 符號(hào) |
那我們?cè)倮^續(xù)往后看。
還是 "abcdefg" 字符串,我們想匹配其中的 "ab" 和 "ef" 兩個(gè)子串,怎么寫呢?按照上面的寫法,就是寫兩個(gè)正則 "ab" 和 "ef" 來(lái)匹配。這樣可以,不過(guò)略顯麻煩。我們寫法如下:
這里我們新加了 "|" 這個(gè)字符,表示 或,即匹配 ab 或者 ef,是不是就方便了許多。
再繼續(xù)看,這次我們需要改變一下待匹配的字符串。
我們?cè)?"acabcdefgh acbbcdefgh accbcdefgh" 字符串中,要匹配 "abcdef","bbcdef","cbcdef" 三個(gè)子串。
讀者朋友們一看,這題非常簡(jiǎn)單,用上面的方法,正則表達(dá)式如下:
寫法正確,不過(guò)略顯繁瑣。我們的寫法如下:
(a|b|c)bcdef是不是有些理解 "|" 的使用了呢。 那我們要匹配 "acabcdef","acbbcdef","accbcdef" 這三個(gè)子串怎么寫呢?
ac(a|b|c)bcdef這下子理解 "|" 的使用了吧。而且我們現(xiàn)在的的寫法,是不是長(zhǎng)得有些 ”像“ 正則表達(dá)式了呢?
2.3 符號(hào) []
我們繼續(xù)。
上面的例子,我們?nèi)绻挥?"|",可以實(shí)現(xiàn)么?
答案是可以的,寫法如下:
是不是看著比上面更清爽一點(diǎn)呢?
我們這里引入了一個(gè)新的字符 "[]"。 這對(duì)中括號(hào)是字符集的意思,里面包含的字符,都是或("|")的關(guān)系。
我們還可以這樣寫:
"[a-c]" 表示的是匹配 a-c 之間的任意字符。
這里對(duì) "[]" 稍微多說(shuō)一些,[] 除了可以放字符集合以及字符范圍以外,還可以做取反操作。
比如 "[^a-c]" 表示的是匹配 a-c 范圍以外其他的字符。"[^0-8]" 表示的是匹配 0-8 范圍以外的其他字符。
到了這里,我們已經(jīng)可以寫一些簡(jiǎn)單的匹配規(guī)則了。
2.4 限制符號(hào) * + ? {}
我們繼續(xù)往下看。
我們現(xiàn)在想匹配 類似 "fooooooooooooooooof" 這樣子的字符串,中間的 "o" 個(gè)數(shù)我們不能確定,上面講到的規(guī)則就有點(diǎn)無(wú)能為力了。
那我們?cè)撛趺磳懩?#xff1f;
這里的 "*" 表示匹配前面的子表達(dá)式零次或多次。
那么有些讀者朋友會(huì)問(wèn)了,如果想匹配至少有一個(gè) "o" 該怎么寫呢?
fo+f這里的 "+" 表示匹配前面的子表達(dá)式一次或多次。
那么讀者朋友又問(wèn)了,如果想匹配 0 個(gè)或者者 1 個(gè) 該怎么寫呢?
fo?f這里的 "?" 表示匹配前面的子表達(dá)式零次或一次。
那么有些讀者朋友又會(huì)問(wèn)了,如果想匹配確定次數(shù)的 "o" 該怎么寫呢?
我們可以這樣寫:
上面的規(guī)則,會(huì)匹配 foof,即匹配 2 個(gè) "o"。
所以,"{n}" 表示匹配前面子表達(dá)式 n 次。
那讀者朋友們?cè)俅伟l(fā)問(wèn),如果想匹配至少 n 個(gè) "o" 該怎么寫呢?
fo{2,}f"{n,}" 表示匹配前面子表達(dá)式至少 n 次。
那讀者朋友們這次不發(fā)問(wèn)了,會(huì)舉一反三了,那如果想匹配 最少 n 個(gè),最多 m 個(gè)呢?
fo{2,5}f"{n,m}" 表示匹配前面子表達(dá)式至少 n 次,至多 m 次。
所以 "*" 等價(jià)于 "{0,}","+" 等價(jià)于 "{1,}","?" 等價(jià)于 "{0,1}"。
到這里,我們能寫的匹配規(guī)則更多了,而且可以說(shuō)大部分匹配運(yùn)用上面的規(guī)則都可以實(shí)現(xiàn)了。
大家可以回頭看看文章開頭貼的幾段正則表達(dá)式,看看是否能看懂了。
當(dāng)然除此之外,正則里的規(guī)則其實(shí)還是不少的,除了上面幾個(gè),我們?cè)倏磶讉€(gè)比較常用的。
2.5 幾個(gè)轉(zhuǎn)義字符
在正則表達(dá)式里,也有一些轉(zhuǎn)義字符,表示一些特殊的含義。 "d" 表示匹配數(shù)字字符,等價(jià)于 "[0-9]"。
"D" 表示匹配非數(shù)字字符,等價(jià)于 "[^0-9]"。
"n" 表示匹配換行符。
"s" 表示匹配任何空白字符,等價(jià)于 "[fnrtv]"。
"S" 表示匹配任何非空白字符,等價(jià)于 "[^fnrtv]"。
2.6 符號(hào) .
符號(hào) "." 會(huì)匹配 "n" 以外的所有字符,也是比較常用的。
2.7 符號(hào) ?
到目前為止,我們已經(jīng)學(xué)習(xí)了大部分常用的正則表達(dá)式規(guī)則,日常開發(fā)基本已經(jīng)夠用了。
不過(guò)使用正則表達(dá)式時(shí),限制字符 "* + ? {}" 默認(rèn)的匹配規(guī)則是貪婪的。什么意思呢?
比如說(shuō)有一個(gè)字符串 "abbbbb",我們使用正則表達(dá)式 "ab+" 去匹配,匹配的結(jié)果是 "abbbbbbb",會(huì)盡可能多的去匹配滿足的字符。
我們?nèi)绻氡M可能少的匹配滿足的字符,那么就在限定符后面加 "?"。
"ab+?" 匹配的結(jié)果就是 ab。
"?" 符號(hào)的非貪婪匹配,在某些情況下也是很有用的。
2.8 符號(hào) ()
最后我們?cè)賮?lái)看一個(gè)符號(hào) "()",小括號(hào)的含義是分組,可以理解為被小括號(hào)包含的子表達(dá)式就是一個(gè)分組,在前面介紹 "|" 的時(shí)候我們使用過(guò)。
不過(guò)分組也分很多類型。
"(pattern)" 小括號(hào)單純的包含了子表達(dá)式,表示此分組可以被捕獲。捕獲的意思就是此分組的內(nèi)容會(huì)被保存下來(lái),后續(xù)可以從匹配的集合中獲取到。
"(?:pattern)" 小括號(hào)中增加了 ?: 前綴,表示此分組不可以被捕獲。后續(xù)匹配的集合中就不會(huì)包含此分組信息。
這樣說(shuō)下來(lái),不太好理解。這里需要結(jié)合具體開發(fā)語(yǔ)言的實(shí)現(xiàn)來(lái)說(shuō)。先留個(gè)懸念,后面會(huì)講到。
"(?=pattern)" 小括號(hào)中增加了 ?= 前綴,表示的是匹配此分組,但是此分組里的內(nèi)容不需要被獲取。
"(?!pattern)" 小括號(hào)中增加了 ?! 前綴,表示的是匹配此分組之外的內(nèi)容,但是此分組里的內(nèi)容不需要被獲取。
舉個(gè)栗子:
正則表達(dá)式 "Windows(?=95|98|NT|2000)" 可以匹配字符串 "Windows2000" 中的 "Windows",但是不能匹配 "Windows3.1" 中的 Windowds。 正則表達(dá)式 "Windows(?!95|98|NT|2000)" 可以匹配字符串 "Windows3.1" 中的 "Windows",但是不能匹配 "Windows2000" 中的 Windowds。
以上就是正則表達(dá)式里一些常見(jiàn)的規(guī)則解析。
2.9 看看文章開頭的例子
我們?cè)谖恼麻_頭放了兩個(gè)例子,這里來(lái)分析一下。
匹配 IP 地址的正則表達(dá)式:
"((2[0-4]d|25[0-5]|[01]?dd?).){3}(2[0-4]d|25[0-5]|[01]?dd?)"
我們分段來(lái)看。
先看第一段 "(2[0-4]d|25[0-5]|[01]?dd?).)",這里用 "|" 分割了三種匹配情況。
第一種是 "2[0-4]d",即三位數(shù)字,第一位是 2,第二位是 0 - 4 之間,第三位是任意數(shù)字。
第二種是 "25[0-5]",三位數(shù)字,第一位是 2,第二位是 5,第三位是 0 - 5 之間。
第三種是 "[01]?dd?",第一位是 0 或者 1,匹配零次或一次,第二位和第三位是任意數(shù)字,第三位數(shù)字匹配零次或一次,也就是 一位數(shù),兩位數(shù),三位數(shù)都可能滿足這種情況。
第一段末尾是 "." 作為分隔符。
再來(lái)看第二段 "{3}",這個(gè)表示前面的子表達(dá)式重復(fù)三次,也就是 IP 地址的前三個(gè)字節(jié)。
再看第三段 "(2[0-4]d|25[0-5]|[01]?dd?)",和第一段是一樣的。
匹配電子郵箱:
"([a-z0-9_.-]+)@([da-z.-]+).([a-z.]{2,6})"
也是分段來(lái)看。
第一段 "([a-z0-9_.-]+)",表示匹配 a-z 范圍內(nèi)的字母,0-9 范圍的數(shù)字,以及 "_",".","-" 三個(gè)字符,"+" 表示至少有一個(gè)字符。
第二段 "@" 表示匹配 "@" 字符。
第三段 "([da-z.-]+)","d" 表示匹配任意數(shù)字,a-z 范圍的字母,".","-" 兩個(gè)字符,"+" 至少有一個(gè)字符。
第四段 "." 表示匹配 "." 字符。
第五段 "([a-z.]{2,6})",表示匹配 a-z 范圍的字母,"." 字符,"{2,6}" 表示至少 2 個(gè)字符,至多 6 個(gè)字符。
經(jīng)過(guò)上面的講解,大家應(yīng)該對(duì)正則表達(dá)式有了進(jìn)一步的了解。
三、在代碼中如何使用
在了解了正則表達(dá)式的規(guī)則以后,我們看一下在實(shí)際代碼中是如何使用的。 這里以 Java 代碼作為示例。
在 Java 中,關(guān)于正則表達(dá)式的主要有兩個(gè)類,Pattern 和 Matcher。
我們看一下具體如何使用。
上面代碼運(yùn)行的結(jié)果如下:
match boy: boy1 match boy number: 1 match boy: boy2 match boy number: 2 match boy: boy3 match boynumber: 3 is phone number: true split res: gril split res: girl split res: split res: girlProcess finished with exit code 0在 Java 中使用正則表達(dá)式分三步走: 1. 寫好正則表達(dá)式 2. Pattern.compile 生成 Pattern 對(duì)象 3. 調(diào)用 Pattern 相關(guān)的正則操作
Pattern 類中有幾個(gè)方法會(huì)比較常用: Pattern#matcher 生成 Matcher,可以對(duì)正則表達(dá)式進(jìn)行匹配,以及獲取匹配的內(nèi)容。
Pattern#split 根據(jù)正則表達(dá)式內(nèi)容劃分字符串。
Matcher 類中也有幾個(gè)方法比較常用: Matcher#find 尋找下一個(gè)滿足規(guī)則的子串,通常用在查找子串中。
Matcher#matches 用來(lái)判斷整個(gè)字符串是否滿足匹配規(guī)則,常用的類似匹配電話號(hào)碼,郵箱等等。
Matcher#group 就是獲取我們?cè)谏厦嬷v到的 "()" 小括號(hào)分組。默認(rèn) group(0) 整個(gè)串的匹配,group(1),group(2) 等等往后順延,就是小括號(hào)內(nèi)的分組。 在我們上面的例子中的正則表達(dá)式是 "boy([0-9])",用來(lái)獲取字符串中的 boy,而括號(hào)中的分組是 boy 的編號(hào),在生成 Matcher 以后,調(diào)用 Matcher#group(0) 獲取的是整個(gè)匹配內(nèi)容,Matcher#group(1) 獲取的是小括號(hào)分組的內(nèi)容。
通過(guò)上面例子,大家應(yīng)該明白 "()" 的作用了吧。
四、規(guī)則全集
下面總結(jié)一下正則表達(dá)式的所有規(guī)則,在使用時(shí)可以查閱,引用自 https://tool.oschina.net/uploads/apidocs/jquery/regexp.html:
總結(jié)
最后,大家只要多多練習(xí),實(shí)際開發(fā)中多使用,掌握正則表達(dá)式不是難事~
參考資料
https://tool.oschina.net/uploads/apidocs/jquery/regexp.html
總結(jié)
以上是生活随笔為你收集整理的正则表达式里转义字符_五分钟搞定正则表达式,如果没搞定,再加两分钟的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【Mail】telnet收发邮件过程
- 下一篇: 天龙八部网单服务器技能修改,天龙八部3门