RegExp正則表達(dá)式基礎(chǔ)語(yǔ)法示例教程
簡(jiǎn)介
在編寫處理字符串的程序或網(wǎng)頁(yè)時(shí),經(jīng)常會(huì)有查找符合某些復(fù)雜規(guī)則的字符串的需要。正則表達(dá)式就是用于描述這些規(guī)則的工具。換句話說(shuō),正則表達(dá)式就是記錄文本規(guī)則的代碼。
很可能你使用過(guò)Windows/Dos下用于文件查找的通配符(wildcard),也就是*和?。如果你想查找某個(gè)目錄下的所有的Word文檔的話,你會(huì)搜索*.doc。在這里,*會(huì)被解釋成任意的字符串。和通配符類似,正則表達(dá)式也是用來(lái)進(jìn)行文本匹配的工具,只不過(guò)比起通配符,它能更精確地描述你的需求——當(dāng)然,代價(jià)就是更復(fù)雜。
假設(shè)你在一篇英文小說(shuō)里查找 hi,你可以使用正則表達(dá)式 hi。
這幾乎是最簡(jiǎn)單的正則表達(dá)式了,它可以精確匹配這樣的字符串:由兩個(gè)字符組成,前一個(gè)字符是 h,后一個(gè)是 i。通常,處理正則表達(dá)式的工具會(huì)提供一個(gè)忽略大小寫的選項(xiàng),如果選中了這個(gè)選項(xiàng),它可以匹配 hi,HI,Hi,hI 這四種情況中的任意一種。
不幸的是,很多單詞里包含hi這兩個(gè)連續(xù)的字符,比如 him,history,high 等等。用 hi來(lái)查找的話,這里邊的 hi 也會(huì)被找出來(lái)。如果要精確地查找 hi 這個(gè)單詞的話,我們應(yīng)該使用\bhi\b。
\b 是正則表達(dá)式規(guī)定的一個(gè)特殊代碼(將其稱之為 元字符),代表著單詞的開頭或結(jié)尾,也就是單詞的分界處。雖然通常英文的單詞是由空格,標(biāo)點(diǎn)符號(hào)或者換行來(lái)分隔的,但是\b并不匹配這些單詞分隔字符中的任何一個(gè),它只匹配一個(gè)位置。
假如你要找的是hi后面不遠(yuǎn)處跟著一個(gè)Lucy,你應(yīng)該用\bhi\b.*\bLucy\b。
這里,.是另一個(gè)元字符,匹配除了換行符以外的任意字符。* 同樣是元字符,不過(guò)它代表的不是字符,也不是位置,而是數(shù)量——它指定* 前邊的內(nèi)容可以連續(xù)重復(fù)使用任意次以使整個(gè)表達(dá)式得到匹配。
因此,.*連在一起就意味著任意數(shù)量的不包含換行的字符?,F(xiàn)在 \bhi\b.*\bLucy\b 的意思就很明顯了:先是一個(gè)單詞 hi,然后是任意個(gè)任意字符(但不能是換行),最后是 Lucy 這個(gè)單詞。
如果同時(shí)使用其它元字符,我們就能構(gòu)造出功能更強(qiáng)大的正則表達(dá)式。比如下面這個(gè)例子:
0\d\d-\d\d\d\d\d\d\d\d匹配這樣的字符串:以 0 開頭,然后是兩個(gè)數(shù)字,然后是一個(gè)連字號(hào)“-”,最后是8個(gè)數(shù)字(也就是中國(guó)的電話號(hào)碼。當(dāng)然,這個(gè)例子只能匹配區(qū)號(hào)為3位的情形)。
這里的\d是個(gè)新的元字符,匹配一位數(shù)字(0,或1,或2,或……)。- 不是元字符,只匹配它本身——連字符(或者減號(hào),或者中橫線,或者隨你怎么稱呼它)。
為了避免那么多煩人的重復(fù),我們也可以這樣寫這個(gè)表達(dá)式:0\d{2}-\d{8}。這里\d后面的{2}({8})的意思是前面\d必須連續(xù)重復(fù)匹配 2 次(8次)。
總的來(lái)說(shuō),正則表達(dá)式一種特殊的編程語(yǔ)言,專門用來(lái)匹配一些特定的字符串。正則表達(dá)式一般不會(huì)單獨(dú)使用,通常會(huì)結(jié)合具體的編程語(yǔ)言(例如 C++、Python、Perl等)或者工具(vim等)使用。
在線工具
正則表達(dá)式本身比較復(fù)雜,可以借助一些工具來(lái)驗(yàn)證所寫的正則表達(dá)式是否符合預(yù)期。
元字符
基本元字符
| Metacharacter | Descriptions | Examples |
|---|---|---|
| \ | 轉(zhuǎn)義字符,使后面的字符失去特殊含義或者標(biāo)記為特殊字符 | \. 匹配實(shí)際的點(diǎn)號(hào)而不是任意字符,\n 匹配一個(gè)換行符 |
| ^ | 匹配字符串的開始位置 | ^abc 匹配以 abc 開頭的字符串 |
| $ | 匹配字符串的結(jié)束位置 | xyz$ 匹配以 “xyz” 結(jié)尾的字符串 |
| . | 匹配除換行符(\n)外的任意單個(gè)字符 | a.b 匹配 “aab”, “a1b”, “a b” 等 |
| * | 匹配前面的子表達(dá)式零次或多次 | zo* 能匹配 “z” 以及 “zoo” |
| + | 匹配前面的子表達(dá)式 1 次或多次 | zo+ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z” |
| ? | 匹配前面的子表達(dá)式零次或一次 | do(es)? 可以匹配 “do” 或 “does” |
| {n} | n 是一個(gè)非負(fù)整數(shù)。匹配確定的 n 次 | o{2} 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的兩個(gè) o |
| {n,} | n 是一個(gè)非負(fù)整數(shù)。至少匹配n 次 | o{2,} 不能匹配 “Bob” 中的 ‘o’,但能匹配 “foooood” 中的所有 o |
| {n,m} | m 和 n 均為非負(fù)整數(shù),其中n <= m。最少匹配 n 次且最多匹配 m 次 | o{1,3} 匹配 “fooooood” 中的前三個(gè) o |
| x|y | 匹配 x 或 y | z|food 能匹配 “z” 或 “food” |
| [xyz] | 字符集合。匹配所包含的任意一個(gè)字符 | [abc] 可以匹配 “plain” 中的 ‘a’。 |
| [^xyz] | 負(fù)值字符集合。匹配未包含的任意字符 | [^abc] 可以匹配 “plain” 中的’p’、‘l’、‘i’、‘n’ |
| [a-z] | 字符范圍。匹配指定范圍內(nèi)的任意字符 | [a-z] 可以匹配 ‘a’ 到 ‘z’ 范圍內(nèi)的任意小寫字母字符 |
| [^a-z] | 負(fù)值字符范圍。匹配任何不在指定范圍內(nèi)的任意字符 | [^a-z] 可以匹配任何不在 ‘a’ 到 ‘z’ 范圍內(nèi)的任意字符 |
| \b | 匹配一個(gè)單詞邊界,也就是指單詞和空格間的位置 | er\b 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’ |
| \B | 匹配非單詞邊界 | er\B 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’ |
| \cx | 匹配由 x 指明的控制字符,x 的值必須為 A-Z 或 a-z 之一。否則,將 c 視為一個(gè)原義的 ‘c’ 字符 | \cM 匹配一個(gè) Control-M 或回車符 |
| \d | 匹配一個(gè)數(shù)字字符 | 等價(jià)于 [0-9] |
| \D | 匹配一個(gè)非數(shù)字字符 | 等價(jià)于 [^0-9] |
| \f | 匹配一個(gè)換頁(yè)符 | 等價(jià)于 \x0c 和 \cL |
| \n | 匹配一個(gè)換行符 | 等價(jià)于 \x0a 和 \cJ |
| \r | 匹配一個(gè)回車符 | 等價(jià)于 \x0d 和 \cM |
| \s | 匹配任何空白字符,包括空格、制表符、換頁(yè)符等等 | 等價(jià)于 [ \f\n\r\t\v] |
| \S | 匹配任何非空白字符 | 等價(jià)于 [^ \f\n\r\t\v] |
| \t | 匹配一個(gè)制表符 | 等價(jià)于 \x09 和 \cI |
| \v | 匹配一個(gè)垂直制表符 | 等價(jià)于 \x0b 和 \cK |
| \w | 匹配字母、數(shù)字、下劃線 | 等價(jià)于 [A-Za-z0-9_] |
| \W | 匹配非字母、數(shù)字、下劃線 | 等價(jià)于 [^A-Za-z0-9_] |
分組與引用
直接在字符后面加上限定符,就可以實(shí)現(xiàn)重復(fù)單個(gè)字符。如果想要重復(fù)多個(gè)字符,比如重復(fù) ab,可以使用小括號(hào)來(lái)指定子表達(dá)式(也叫做分組),然后指定這個(gè)子表達(dá)式的重復(fù)次數(shù)。
例如,(ab)+ 可以匹配 “ab”、“abab”、“ababab” 等,但不能匹配 “a” 或 “b”。
- 捕獲分組
正則表達(dá)式中有幾種不同類型的分組,捕獲分組是最常見的分組形式,它會(huì)捕獲匹配的內(nèi)容并分配一個(gè)編號(hào)(從 1 開始)。后續(xù)可以基于編號(hào)訪問(wèn)分組中的內(nèi)容。
示例:
(\d{4})-(\d{2})-(\d{2}) # 匹配日期格式 YYYY-MM-DD
這個(gè)表達(dá)式會(huì)創(chuàng)建3個(gè)分組:① 4位數(shù)字的年份;② 2位數(shù)字的月份;③ 2位數(shù)字的日期
- 分組引用
分組最強(qiáng)大的功能之一是可以在正則表達(dá)式內(nèi)部或外部引用已匹配的內(nèi)容。
在正則表達(dá)式內(nèi)部引用前面的分組,使用 \num,其中 num 是分組索引。
(\w+) \1 # 匹配重復(fù)的單詞,如 "hello hello"
這個(gè) pattern 會(huì)匹配兩個(gè)相同的單詞,中間用空格分隔,其中 \1 就是對(duì)分組的引用。
- 非捕獲分組
使用 (?:pattern) 語(yǔ)法,表示只分組但不捕獲。
例如,(?:Mr|Ms|Mrs)\. (\w+) 表示匹配 “Mr. Smith” 但只捕獲 “Smith”。
- 命名分組與引用
在一些高級(jí)語(yǔ)言中,還可以為分組指定名稱,提高可讀性(不同語(yǔ)言語(yǔ)法可能不同)。
例如,在 Python 中對(duì)分組進(jìn)行命令的方法如下:
### Named Capturing Group
(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})
### Reference
(?P<word>\w+) (?P=word)
運(yùn)算符優(yōu)先級(jí)
正則表達(dá)式從左到右進(jìn)行計(jì)算,并遵循優(yōu)先級(jí)順序,這與算術(shù)表達(dá)式非常類似。
相同優(yōu)先級(jí)的從左到右進(jìn)行運(yùn)算,不同優(yōu)先級(jí)的運(yùn)算先高后低。
正則表達(dá)式中,各種運(yùn)算符的優(yōu)先級(jí)順序如下:
| 優(yōu)先級(jí) | 運(yùn)算符 | 描述 |
|---|---|---|
| 1 | \ | 轉(zhuǎn)義符 |
| 2 | ()、[] | 圓括號(hào)和方括號(hào) |
| 3 | *、 +、 ?、 {n}、{n,}、{n,m} | 限定符 |
| 4 | ^、$、\任何元字符、任何字符 | 定位點(diǎn)和序列(即:位置和順序) |
| 5 | | | "或"操作 |
貪婪模式
當(dāng)正則表達(dá)式中包含能接受重復(fù)的限定符時(shí),通常的行為是(在使整個(gè)表達(dá)式能得到匹配的前提下)匹配盡可能多的字符。以表達(dá)式a.*b 為例,它將會(huì)匹配最長(zhǎng)的以a開始,以b結(jié)束的字符串。如果用它來(lái)搜索aabab的話,它會(huì)匹配整個(gè)字符串a(chǎn)abab。這被稱為貪婪匹配。
有時(shí),我們更需要懶惰匹配,也就是匹配盡可能少的字符。前面給出的限定符都可以被轉(zhuǎn)化為懶惰匹配模式,只要在它后面加上一個(gè)?。
這樣.*?就意味著匹配任意數(shù)量的重復(fù),但是在能使整個(gè)匹配成功的前提下使用最少的重復(fù)
a.*?b 匹配最短的,以a開始,以b結(jié)束的字符串。如果把它應(yīng)用于 aabab 的話,它會(huì)匹配 aab(第一到第三個(gè)字符)和ab(第四到第五個(gè)字符)。
為什么第一個(gè)匹配是aab(第一到第三個(gè)字符)而不是ab(第二到第三個(gè)字符)?簡(jiǎn)單地說(shuō),因?yàn)檎齽t表達(dá)式有另一條規(guī)則,比懶惰/貪婪規(guī)則的優(yōu)先級(jí)更高:最先開始的匹配擁有最高的優(yōu)先權(quán)。
對(duì)于其他的的重復(fù)限定符,都支持使用 ? 進(jìn)入懶惰模式:

總結(jié)
到此這篇關(guān)于RegExp正則表達(dá)式基礎(chǔ)語(yǔ)法的文章就介紹到這了,更多相關(guān)RegExp正則表達(dá)式語(yǔ)法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
教你用正則表達(dá)式提取數(shù)字和小數(shù)點(diǎn)
最近開發(fā)遇到一個(gè)新的東西,需要將里面的數(shù)字提取出來(lái),下面這篇文章主要給大家介紹了關(guān)于用正則表達(dá)式提取數(shù)字和小數(shù)點(diǎn)的相關(guān)資料,需要的朋友可以參考下2022-09-09
最常用的15個(gè)前端表單驗(yàn)證JS正則表達(dá)式
在表單驗(yàn)證中,使用正則表達(dá)式來(lái)驗(yàn)證正確與否是一個(gè)很頻繁的操作,本文收集整理了15個(gè)常用的JavaScript正則表達(dá)式,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-07-07
淺談js正則字面量//與new RegExp的執(zhí)行效率
以前看到很多文章都說(shuō) 字面量 會(huì)比 new 對(duì)象 形式效率高,但是在正則這里,好像不是這么回事,具體的請(qǐng)看下面的分析2020-04-04
正則表達(dá)式re.sub替換不完整的問(wèn)題及完整解決方案
re.sub是個(gè)正則表達(dá)式方面的函數(shù),用來(lái)實(shí)現(xiàn)通過(guò)正則表達(dá)式,實(shí)現(xiàn)比普通字符串的replace更加強(qiáng)大的替換功能。這篇文章主要介紹了正則表達(dá)式re.sub替換不完整的問(wèn)題及解決方案,需要的朋友可以參考下2018-08-08

