精通正則表達(dá)式 java正則表達(dá)式經(jīng)典實(shí)例

正則表達(dá)式,又稱規(guī)則表達(dá)式(英語(yǔ):Regular Expression,在代碼中常簡(jiǎn)寫為regex、regexp或RE),計(jì)算機(jī)科學(xué)的一個(gè)概念。正則表通常被用來(lái)檢索、替換那些符合某個(gè)模式(規(guī)則)的文本。

許多程序設(shè)計(jì)語(yǔ)言都支持利用正則表達(dá)式進(jìn)行字符串操作。例如,在Perl中就內(nèi)建了一個(gè)功能強(qiáng)大的正則表達(dá)式引擎。正則表達(dá)式這個(gè)概念最初是由Unix中的工具軟件(例如sed和grep)普及開(kāi)的。正則表達(dá)式通??s寫成"regex",單數(shù)有regexp、regex,復(fù)數(shù)有regexps、regexes、regexen。

正則表達(dá)式

正則表達(dá)式,又稱規(guī)則表達(dá)式,英文名為Regular Expression,在代碼中常簡(jiǎn)寫為regex、regexp或RE,是計(jì)算機(jī)科學(xué)的一個(gè)概念。正則表通常被用來(lái)檢索、替換那些符合某個(gè)模式(規(guī)則)的文本。

正則表達(dá)式是對(duì)字符串(包括普通字符(例如,a 到 z 之間的字母)和特殊字符(稱為"元字符"))操作的一種邏輯公式,就是用事先定義好的一些特定字符、及這些特定字符的組合,組成一個(gè)"規(guī)則字符串",這個(gè)"規(guī)則字符串"用來(lái)表達(dá)對(duì)字符串的一種過(guò)濾邏輯。正則表達(dá)式是一種文本模式,模式描述在搜索文本時(shí)要匹配的一個(gè)或多個(gè)字符串。[1]

折疊編輯本段起源

正則表達(dá)式的"鼻祖"或許可一直追溯到科學(xué)家對(duì)人類神經(jīng)系統(tǒng)工作原理的早期研究。美國(guó)新澤西州的Warren McCulloch和出生在美國(guó)底特律的Walter Pitts這兩位神經(jīng)生理方面的科學(xué)家,研究出了一種用數(shù)學(xué)方式來(lái)描述神經(jīng)網(wǎng)絡(luò)的新方法,他們創(chuàng)造性地將神經(jīng)系統(tǒng)中的神經(jīng)元描述成了小而簡(jiǎn)單的自動(dòng)控制元,從而作出了一項(xiàng)偉大的工作革新。

在1951 年,一位名叫Stephen Kleene的數(shù)學(xué)科學(xué)家,他在Warren McCulloch和Walter Pitts早期工作的基礎(chǔ)之上,發(fā)表了一篇題目是《神經(jīng)網(wǎng)事件的表示法》的論文,利用稱之為正則集合的數(shù)學(xué)符號(hào)來(lái)描述此模型,引入了正則表達(dá)式的概念。正則表達(dá)式被作為用來(lái)描述其稱之為"正則集的代數(shù)"的一種表達(dá)式,因而采用了"正則表達(dá)式"這個(gè)術(shù)語(yǔ)。

之后一段時(shí)間,人們發(fā)現(xiàn)可以將這一工作成果應(yīng)用于其他方面。Ken Thompson就把這一成果應(yīng)用于計(jì)算搜索算法的一些早期研究,Ken Thompson是 Unix的主要發(fā)明人,也就是大名鼎鼎的Unix之父。Unix之父將此符號(hào)系統(tǒng)引入編輯器QED,然后是Unix上的編輯器ed,并最終引入grep。Jeffrey Friedl 在其著作《Mastering Regular Expressions (2nd edition)》(中文版譯作:精通正則表達(dá)式,已出到第三版)中對(duì)此作了進(jìn)一步闡述講解,如果你希望更多了解正則表達(dá)式理論和歷史,推薦你看看這本書。

自此以后,正則表達(dá)式被廣泛地應(yīng)用到各種UNIX或類似于UNIX的工具中,如大家熟知的Perl。Perl的正則表達(dá)式源自于Henry Spencer編寫的regex,之后已演化成了pcre(Perl兼容正則表達(dá)式Perl Compatible Regular Expressions),pcre是一個(gè)由Philip Hazel開(kāi)發(fā)的、為很多現(xiàn)代工具所使用的庫(kù)。正則表達(dá)式的第一個(gè)實(shí)用應(yīng)用程序即為Unix中的 qed 編輯器。

然后,正則表達(dá)式在各種計(jì)算機(jī)語(yǔ)言或各種應(yīng)用領(lǐng)域得到了廣大的應(yīng)用和發(fā)展,演變成為計(jì)算機(jī)技術(shù)森林中的一只形神美麗且聲音動(dòng)聽(tīng)的百靈鳥。

以上是關(guān)于正則表達(dá)式的起源和發(fā)展的歷史描述,如今正則表達(dá)式在基于文本的編輯器和搜索工具中依然占據(jù)著一個(gè)非常重要的地位。

在最近的六十年中,正則表達(dá)式逐漸從模糊而深?yuàn)W的數(shù)學(xué)概念,發(fā)展成為在計(jì)算機(jī)各類工具和軟件包應(yīng)用中的主要功能。不僅僅眾多UNIX工具支持正則表達(dá)式,近二十年來(lái),在WINDOWS的陣營(yíng)下,正則表達(dá)式的思想和應(yīng)用在大部分 Windows 開(kāi)發(fā)者工具包中得到支持和嵌入應(yīng)用!從正則式在Microsoft Visual Basic 6 或 Microsoft VBScript到.NET Framework中的探索和發(fā)展,WINDOWS系列產(chǎn)品對(duì)正則表達(dá)式的支持發(fā)展到無(wú)與倫比的高度,幾乎所有 Microsoft 開(kāi)發(fā)者和所有.NET語(yǔ)言都可以使用正則表達(dá)式。如果你是一位接觸計(jì)算機(jī)語(yǔ)言的工作者,那么你會(huì)在主流操作系統(tǒng)(*nix[Linux, Unix等]、Windows、HP、BeOS等)、主流的開(kāi)發(fā)語(yǔ)言(delphi、Scala、PHP、C#、Java、C++、Objective-c、Swift、VB、Javascript、Ruby以及Python等)、數(shù)以億萬(wàn)計(jì)的各種應(yīng)用軟件中,都可以看到正則表達(dá)式優(yōu)美的舞姿。

正則表達(dá)式(regular expression)描述了一種字符串匹配的模式(pattern),可以用來(lái)檢查一個(gè)串是否含有某種子串、將匹配的子串替換或者從某個(gè)串中取出符合某個(gè)條件的子串等。

例如:

  • runoo+b,可以匹配 runoob、runooob、runoooooob 等,+ 號(hào)代表前面的字符必須至少出現(xiàn)一次(1次或多次)。
  • runoo*b,可以匹配 runob、runoob、runoooooob 等,* 號(hào)代表字符可以不出現(xiàn),也可以出現(xiàn)一次或者多次(0次、或1次、或多次)。
  • colou?r 可以匹配 color 或者 colour,? 問(wèn)號(hào)代表前面的字符最多只可以出現(xiàn)一次(0次、或1次)。

構(gòu)造正則表達(dá)式的方法和創(chuàng)建數(shù)學(xué)表達(dá)式的方法一樣。也就是用多種元字符與運(yùn)算符可以將小的表達(dá)式結(jié)合在一起來(lái)創(chuàng)建更大的表達(dá)式。正則表達(dá)式的組件可以是單個(gè)的字符、字符集合、字符范圍、字符間的選擇或者所有這些組件的任意組合。

正則表達(dá)式是由普通字符(例如字符 a 到 z)以及特殊字符(稱為"元字符")組成的文字模式。模式描述在搜索文本時(shí)要匹配的一個(gè)或多個(gè)字符串。正則表達(dá)式作為一個(gè)模板,將某個(gè)字符模式與所搜索的字符串進(jìn)行匹配。


普通字符

普通字符包括沒(méi)有顯式指定為元字符的所有可打印和不可打印字符。這包括所有大寫和小寫字母、所有數(shù)字、所有標(biāo)點(diǎn)符號(hào)和一些其他符號(hào)。


非打印字符

非打印字符也可以是正則表達(dá)式的組成部分。下表列出了表示非打印字符的轉(zhuǎn)義序列:

字符 描述
\cx 匹配由x指明的控制字符。例如, \cM 匹配一個(gè) Control-M 或回車符。x 的值必須為 A-Z 或 a-z 之一。否則,將 c 視為一個(gè)原義的 'c' 字符。
\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。

特殊字符

所謂特殊字符,就是一些有特殊含義的字符,如上面說(shuō)的 runoo*b 中的 *,簡(jiǎn)單的說(shuō)就是表示任何字符串的意思。如果要查找字符串中的 * 符號(hào),則需要對(duì) * 進(jìn)行轉(zhuǎn)義,即在其前加一個(gè) \: runo\*ob 匹配 runo*ob。

許多元字符要求在試圖匹配它們時(shí)特別對(duì)待。若要匹配這些特殊字符,必須首先使字符"轉(zhuǎn)義",即,將反斜杠字符\ 放在它們前面。下表列出了正則表達(dá)式中的特殊字符:

特別字符 描述
$ 匹配輸入字符串的結(jié)尾位置。如果設(shè)置了 RegExp 對(duì)象的 Multiline 屬性,則 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,請(qǐng)使用 \$。
( ) 標(biāo)記一個(gè)子表達(dá)式的開(kāi)始和結(jié)束位置。子表達(dá)式可以獲取供以后使用。要匹配這些字符,請(qǐng)使用 \( 和 \)。
* 匹配前面的子表達(dá)式零次或多次。要匹配 * 字符,請(qǐng)使用 \*。
+ 匹配前面的子表達(dá)式一次或多次。要匹配 + 字符,請(qǐng)使用 \+。
. 匹配除換行符 \n 之外的任何單字符。要匹配 . ,請(qǐng)使用 \. 。
[ 標(biāo)記一個(gè)中括號(hào)表達(dá)式的開(kāi)始。要匹配 [,請(qǐng)使用 \[。
? 匹配前面的子表達(dá)式零次或一次,或指明一個(gè)非貪婪限定符。要匹配 ? 字符,請(qǐng)使用 \?。
\ 將下一個(gè)字符標(biāo)記為或特殊字符、或原義字符、或向后引用、或八進(jìn)制轉(zhuǎn)義符。例如, 'n' 匹配字符 'n'。'\n' 匹配換行符。序列 '\\' 匹配 "\",而 '\(' 則匹配 "("。
^ 匹配輸入字符串的開(kāi)始位置,除非在方括號(hào)表達(dá)式中使用,此時(shí)它表示不接受該字符集合。要匹配 ^ 字符本身,請(qǐng)使用 \^。
{ 標(biāo)記限定符表達(dá)式的開(kāi)始。要匹配 {,請(qǐng)使用 \{。
| 指明兩項(xiàng)之間的一個(gè)選擇。要匹配 |,請(qǐng)使用 \|。

限定符

限定符用來(lái)指定正則表達(dá)式的一個(gè)給定組件必須要出現(xiàn)多少次才能滿足匹配。有 *+?{n}{n,}{n,m} 共6種。

正則表達(dá)式的限定符有:

字符 含意
\ 做為轉(zhuǎn)意,即通常在"\"后面的字符不按原來(lái)意義解釋,如/b/匹配字符"b",當(dāng)b前面加了反斜桿后/\b/,轉(zhuǎn)意為匹配一個(gè)單詞的邊界。
-或-
對(duì)正則表達(dá)式功能字符的還原,如"*"匹配它前面元字符0次或多次,/a*/將匹配a,aa,aaa,加了"\"后,/a\*/將只匹配"a*"。
^ 匹配一個(gè)輸入或一行的開(kāi)頭,/^a/匹配"an A",而不匹配"An a"
$ 匹配一個(gè)輸入或一行的結(jié)尾,/a$/匹配"An a",而不匹配"an A"
* 匹配前面元字符0次或多次,/ba*/將匹配b,ba,baa,baaa
+ 匹配前面元字符1次或多次,/ba*/將匹配ba,baa,baaa
? 匹配前面元字符0次或1次,/ba*/將匹配b,ba
(x) 匹配x保存x在名為$1...$9的變量中
x|y 匹配x或y
{n} 精確匹配n次
{n,} 匹配n次以上
{n,m} 匹配n-m次
[xyz] 字符集(character set),匹配這個(gè)集合中的任一一個(gè)字符(或元字符)
[^xyz] 不匹配這個(gè)集合中的任何一個(gè)字符
[\b] 匹配一個(gè)退格符
\b 匹配一個(gè)單詞的邊界
\B 匹配一個(gè)單詞的非邊界
\cX 這兒,X是一個(gè)控制符,/\cM/匹配Ctrl-M
\d 匹配一個(gè)字?jǐn)?shù)字符,/\d/ = /[0-9]/
\D 匹配一個(gè)非字?jǐn)?shù)字符,/\D/ = /[^0-9]/
\n 匹配一個(gè)換行符
\r 匹配一個(gè)回車符
\s 匹配一個(gè)空白字符,包括\n,\r,\f,\t,\v等
\S 匹配一個(gè)非空白字符,等于/[^\n\f\r\t\v]/
\t 匹配一個(gè)制表符
\v 匹配一個(gè)重直制表符
\w 匹配一個(gè)可以組成單詞的字符(alphanumeric,這是我的意譯,含數(shù)字),包括下劃線,如[\w]匹配"$5.98"中的5,等于[a-zA-Z0-9]
\W 匹配一個(gè)不可以組成單詞的字符,如[\W]匹配"$5.98"中的$,等于[^a-zA-Z0-9]。
用re = new RegExp("pattern",["flags"]) 的方式比較好
pattern : 正則表達(dá)式
flags: g (全文查找出現(xiàn)的所有 pattern)
i (忽略大小寫)
m (多行查找)
vaScript動(dòng)態(tài)正則表達(dá)式問(wèn)題請(qǐng)問(wèn)正則表達(dá)式可以動(dòng)態(tài)生成嗎?
例如JavaScript中:
var str = "strTemp";
要生成:
var re = /strTemp/;
如果是字符連接:
var re = "/" + str + "/"即可
但是要生成表達(dá)式,可以實(shí)現(xiàn)嗎?怎樣實(shí)現(xiàn)?
[JAVA] javascript 正則表達(dá)式
秋雨葉 發(fā)表于 2004-12-9 14:54:13
正則表達(dá)式是一個(gè)描述字符模式的對(duì)象。
JavaScript的RegExp對(duì)象和String對(duì)象定義了使用正則表達(dá)式來(lái)執(zhí)行強(qiáng)大的模式匹配和文本檢索與替換函數(shù)的方法.

在JavaScript中,正則表達(dá)式是由一個(gè)RegExp對(duì)象表示的.當(dāng)然,可以使用一個(gè)RegExp()構(gòu)造函數(shù)來(lái)創(chuàng)建RegExp對(duì)象,
也可以用JavaScript 1.2中的新添加的一個(gè)特殊語(yǔ)法來(lái)創(chuàng)建RegExp對(duì)象.就像字符串直接量被定義為包含在引號(hào)內(nèi)的字符一樣,
正則表達(dá)式直接量也被定義為包含在一對(duì)斜杠(/)之間的字符.所以,JavaScript可能會(huì)包含如下的代碼:

var pattern = /s$/;

這行代碼創(chuàng)建一個(gè)新的RegExp對(duì)象,并將它賦給變量parttern.這個(gè)特殊的RegExp對(duì)象和所有以字母"s"結(jié)尾的字符串都匹配.用RegExp()也可以定義
一個(gè)等價(jià)的正則表達(dá)式,代碼如下:

var pattern = new RegExp("s$");

無(wú)論是用正則表達(dá)式直接量還是用構(gòu)造函數(shù)RegExp(),創(chuàng)建一個(gè)RegExp對(duì)象都是比較容易的.較為困難的任務(wù)是用正則表達(dá)式語(yǔ)法來(lái)描述字符的模式.
JavaScript采用的是Perl語(yǔ)言正則表達(dá)式語(yǔ)法的一個(gè)相當(dāng)完整的子集.

正則表達(dá)式的模式規(guī)范是由一系列字符構(gòu)成的.大多數(shù)字符(包括所有字母數(shù)字字符)描述的都是按照字面意思進(jìn)行匹配的字符.這樣說(shuō)來(lái),正則表達(dá)式/java/就和
所有包含子串 "java" 的字符串相匹配.雖然正則表達(dá)式中的其它字符不是按照字面意思進(jìn)行匹配的,但它們都具有特殊的意義.正則表達(dá)式 /s$/ 包含兩個(gè)字符.
第一個(gè)特殊字符 "s" 是按照字面意思與自身相匹配.第二個(gè)字符 "$" 是一個(gè)特殊字符,它所匹配的是字符串的結(jié)尾.所以正則表達(dá)式 /s$/ 匹配的就是以字母 "s" 結(jié)尾
的字符串.


1.直接量字符

我們已經(jīng)發(fā)現(xiàn)了,在正則表達(dá)式中所有的字母字符和數(shù)字都是按照字面意思與自身相匹配的.JavaScript的正則表達(dá)式還通過(guò)以反斜杠(\)開(kāi)頭的轉(zhuǎn)義序列支持某些非

字母字符.例如,序列 "\n" 在字符串中匹配的是一個(gè)直接量換行符.在正則表達(dá)式中,許多標(biāo)點(diǎn)符號(hào)都有特殊的含義.下面是這些字符和它們的含義:

正則表達(dá)式的直接量字符

字符 匹配
________________________________
字母數(shù)字字符 自身
\ f 換頁(yè)符
\ n 換行符
\ r 回車
\ t 制表符
\ v 垂直制表符
\ / 一個(gè) / 直接量
\ \ 一個(gè) \ 直接量
\ . 一個(gè) . 直接量
\ * 一個(gè) * 直接量
\ + 一個(gè) + 直接量
\ ? 一個(gè) ? 直接量
\ | 一個(gè) | 直接量
\ ( 一個(gè) ( 直接量
\ ) 一個(gè) ) 直接量
\ [ 一個(gè) [ 直接量
\ ] 一個(gè) ] 直接量
\ { 一個(gè) { 直接量
\ } 一個(gè) } 直接量
\ XXX 由十進(jìn)制數(shù) XXX 指 定的ASCII碼字符
\ Xnn 由十六進(jìn)制數(shù) nn 指定的ASCII碼字符
\ cX 控制字符^X. 例如, \cI等價(jià)于 \t, \cJ等價(jià)于 \n

___________________________________________________

如果想在正則表達(dá)式中使用特殊的標(biāo)點(diǎn)符號(hào),必須在它們之前加上一個(gè) "\" .


2.字符類

將單獨(dú)的直接符放進(jìn)中括號(hào)內(nèi)就可以組合成字符類.一個(gè)字符類和它所包含的任何一個(gè)字符都匹配,所以正則表達(dá)式 / [abc] / 和字母 "a" , "b" , "c" 中的任何一個(gè)
都匹配.另外還可以定義否定字符類,這些類匹配的是除那些包含在中括號(hào)之內(nèi)的字符外的所有字符.定義否定字符尖時(shí),要將一個(gè) ^ 符號(hào)作為從左中括號(hào)算起的第
一個(gè)字符.正則表達(dá)式的集合是 / [a-zA-z0-9] / .

由于某些字符類非常常用,所以JavaScript的正則表達(dá)式語(yǔ)法包含一些特殊字符和轉(zhuǎn)義序列來(lái)表示這些常用的類.例如, \s 匹配的是空格符,制表符和其它空白符, \s
匹配的則是空白符之外的任何字符.

正則表灰式的字符類

字符 匹配
____________________________________________________
[...] 位于括號(hào)之內(nèi)的任意字符
[^...] 不在括號(hào)之中的任意字符
. 除了換行符之外的任意字符,等價(jià)于[^\n]
\w 任何單字字符, 等價(jià)于[a-zA-Z0-9]
\W 任何非單字字符,等價(jià)于[^a-zA-Z0-9]
\s 任何空白符,等價(jià)于[\ t \ n \ r \ f \ v]
\S 任何非空白符,等價(jià)于[^\ t \ n \ r \ f \ v]
\d 任何數(shù)字,等價(jià)于[0-9]
\D 除了數(shù)字之外的任何字符,等價(jià)于[^0-9]
[\b] 一個(gè)退格直接量(特例)
________________________________________________________________

3.復(fù)制

用以上的正則表式的語(yǔ)法,可以把兩位數(shù)描述成 / \ d \ d /,把四位數(shù)描述成 / \d \ d \ d \ d /.但我們還沒(méi)有一種方法可以用來(lái)描述具有任意多數(shù)位的數(shù)字或者是一個(gè)

字符串.這個(gè)串由三個(gè)字符以及跟隨在字母之后的一位數(shù)字構(gòu)成.這些復(fù)雜的模式使用的正則表達(dá)式語(yǔ)法指定了該表達(dá)式中每個(gè)元素要重復(fù)出現(xiàn)的次數(shù).

指定復(fù)制的字符總是出現(xiàn)在它們所作用的模式后面.由于某種復(fù)制類型相當(dāng)常用.所以有一些特殊的字符專門用于表示它們.例如: +號(hào)匹配的就是復(fù)制前一模式一次

或多次的模式.下面的表列出了復(fù)制語(yǔ)法.先看一個(gè)例子:

/\d{2, 4}/ //匹配2到4間的數(shù)字.

/\w{3} \d?/ //匹配三個(gè)單字字符和一個(gè)任意的數(shù)字.

/\s+java\s+/ //匹配字符串"java" ,并且該串前后可以有一個(gè)或多個(gè)空格.

/[^"] * / //匹配零個(gè)或多個(gè)非引號(hào)字符.

1. 正則表達(dá)式規(guī)則

1.1 普通字符

字母、數(shù)字、漢字、下劃線、以及后邊章節(jié)中沒(méi)有特殊定義的標(biāo)點(diǎn)符號(hào),都是"普通字符"。表達(dá)式中的普通字符,在匹配一個(gè)字符串的時(shí)候,匹配與之相同的一個(gè)字符。

??? 點(diǎn)擊測(cè)試 舉例1:表達(dá)式 "c",在匹配字符串 "abcde" 時(shí),匹配結(jié)果是:成功;匹配到的內(nèi)容是:"c";匹配到的位置是:開(kāi)始于2,結(jié)束于3。(注:下標(biāo)從0開(kāi)始還是從1開(kāi)始,因當(dāng)前編程語(yǔ)言的不同而可能不同)

??? 點(diǎn)擊測(cè)試 舉例2:表達(dá)式 "bcd",在匹配字符串 "abcde" 時(shí),匹配結(jié)果是:成功;匹配到的內(nèi)容是:"bcd";匹配到的位置是:開(kāi)始于1,結(jié)束于4。


1.2 簡(jiǎn)單的轉(zhuǎn)義字符

一些不便書寫的字符,采用在前面加 "\" 的方法。這些字符其實(shí)我們都已經(jīng)熟知了。

表達(dá)式 可匹配
\r, \n 代表回車和換行符
\t 制表符
\\ 代表 "\" 本身

還有其他一些在后邊章節(jié)中有特殊用處的標(biāo)點(diǎn)符號(hào),在前面加 "\" 后,就代表該符號(hào)本身。比如:^, $ 都有特殊意義,如果要想匹配字符串中 "^" 和 "$" 字符,則表達(dá)式就需要寫成 "\^" 和 "\$"。

表達(dá)式 可匹配
\^ 匹配 ^ 符號(hào)本身
\$ 匹配 $ 符號(hào)本身
\. 匹配小數(shù)點(diǎn)(.)本身

這些轉(zhuǎn)義字符的匹配方法與 "普通字符" 是類似的。也是匹配與之相同的一個(gè)字符。

??? 點(diǎn)擊測(cè)試 舉例1:表達(dá)式 "\$d",在匹配字符串 "abc$de" 時(shí),匹配結(jié)果是:成功;匹配到的內(nèi)容是:"$d";匹配到的位置是:開(kāi)始于3,結(jié)束于5。


1.3 能夠與 '多種字符' 匹配的表達(dá)式

正則表達(dá)式中的一些表示方法,可以匹配 '多種字符' 其中的任意一個(gè)字符。比如,表達(dá)式 "\d" 可以匹配任意一個(gè)數(shù)字。雖然可以匹配其中任意字符,但是只能是一個(gè),不是多個(gè)。這就好比玩撲克牌時(shí)候,大小王可以代替任意一張牌,但是只能代替一張牌。

表達(dá)式 可匹配
\d 任意一個(gè)數(shù)字,0~9 中的任意一個(gè)
\w 任意一個(gè)字母或數(shù)字或下劃線,也就是 A~Z,a~z,0~9,_ 中任意一個(gè)
\s 包括空格、制表符、換頁(yè)符等空白字符的其中任意一個(gè)
. 小數(shù)點(diǎn)可以匹配除了換行符(\n)以外的任意一個(gè)字符

點(diǎn)擊測(cè)試 舉例1:表達(dá)式 "\d\d",在匹配 "abc123" 時(shí),匹配的結(jié)果是:成功;匹配到的內(nèi)容是:"12";匹配到的位置是:開(kāi)始于3,結(jié)束于5。

??? 點(diǎn)擊測(cè)試 舉例2:表達(dá)式 "a.\d",在匹配 "aaa100" 時(shí),匹配的結(jié)果是:成功;匹配到的內(nèi)容是:"aa1";匹配到的位置是:開(kāi)始于1,結(jié)束于4。


1.4 自定義能夠匹配 '多種字符' 的表達(dá)式

使用方括號(hào) [ ] 包含一系列字符,能夠匹配其中任意一個(gè)字符。用 [^ ] 包含一系列字符,則能夠匹配其中字符之外的任意一個(gè)字符。同樣的道理,雖然可以匹配其中任意一個(gè),但是只能是一個(gè),不是多個(gè)。

表達(dá)式 可匹配
[ab5@] 匹配 "a" 或 "b" 或 "5" 或 "@"
[^abc] 匹配 "a","b","c" 之外的任意一個(gè)字符
[f-k] 匹配 "f"~"k" 之間的任意一個(gè)字母
[^A-F0-3] 匹配 "A"~"F","0"~"3" 之外的任意一個(gè)字符

點(diǎn)擊測(cè)試 舉例1:表達(dá)式 "[bcd][bcd]" 匹配 "abc123" 時(shí),匹配的結(jié)果是:成功;匹配到的內(nèi)容是:"bc";匹配到的位置是:開(kāi)始于1,結(jié)束于3。

??? 點(diǎn)擊測(cè)試 舉例2:表達(dá)式 "[^abc]" 匹配 "abc123" 時(shí),匹配的結(jié)果是:成功;匹配到的內(nèi)容是:"1";匹配到的位置是:開(kāi)始于3,結(jié)束于4。


1.5 修飾匹配次數(shù)的特殊符號(hào)

前面章節(jié)中講到的表達(dá)式,無(wú)論是只能匹配一種字符的表達(dá)式,還是可以匹配多種字符其中任意一個(gè)的表達(dá)式,都只能匹配一次。如果使用表達(dá)式再加上修飾匹配次數(shù)的特殊符號(hào),那么不用重復(fù)書寫表達(dá)式就可以重復(fù)匹配。

??? 使用方法是:"次數(shù)修飾"放在"被修飾的表達(dá)式"后邊。比如:"[bcd][bcd]" 可以寫成 "[bcd]{2}"。

表達(dá)式 作用
{n} 表達(dá)式重復(fù)n次,比如:點(diǎn)擊測(cè)試 "\w{2}" 相當(dāng)于 "\w\w";點(diǎn)擊測(cè)試 "a{5}" 相當(dāng)于 "aaaaa"
{m,n} 表達(dá)式至少重復(fù)m次,最多重復(fù)n次,比如:點(diǎn)擊測(cè)試 "ba{1,3}"可以匹配 "ba"或"baa"或"baaa"
{m,} 表達(dá)式至少重復(fù)m次,比如:點(diǎn)擊測(cè)試 "\w\d{2,}"可以匹配 "a12","_456","M12344"...
? 匹配表達(dá)式0次或者1次,相當(dāng)于 {0,1},比如:點(diǎn)擊測(cè)試 "a[cd]?"可以匹配 "a","ac","ad"
+ 表達(dá)式至少出現(xiàn)1次,相當(dāng)于 {1,},比如:點(diǎn)擊測(cè)試 "a+b"可以匹配 "ab","aab","aaab"...
* 表達(dá)式不出現(xiàn)或出現(xiàn)任意次,相當(dāng)于 {0,},比如:點(diǎn)擊測(cè)試 "\^*b"可以匹配 "b","^^^b"...

點(diǎn)擊測(cè)試 舉例1:表達(dá)式 "\d+\.?\d*" 在匹配 "It costs $12.5" 時(shí),匹配的結(jié)果是:成功;匹配到的內(nèi)容是:"12.5";匹配到的位置是:開(kāi)始于10,結(jié)束于14。

??? 點(diǎn)擊測(cè)試 舉例2:表達(dá)式 "go{2,8}gle" 在匹配 "Ads by goooooogle" 時(shí),匹配的結(jié)果是:成功;匹配到的內(nèi)容是:"goooooogle";匹配到的位置是:開(kāi)始于7,結(jié)束于17。


1.6 其他一些代表抽象意義的特殊符號(hào)

一些符號(hào)在表達(dá)式中代表抽象的特殊意義:

表達(dá)式 作用
^ 與字符串開(kāi)始的地方匹配,不匹配任何字符
$ 與字符串結(jié)束的地方匹配,不匹配任何字符
\b 匹配一個(gè)單詞邊界,也就是單詞和空格之間的位置,不匹配任何字符

進(jìn)一步的文字說(shuō)明仍然比較抽象,因此,舉例幫助大家理解。

??? 點(diǎn)擊測(cè)試 舉例1:表達(dá)式 "^aaa" 在匹配 "xxx aaa xxx" 時(shí),匹配結(jié)果是:失敗。因?yàn)?"^" 要求與字符串開(kāi)始的地方匹配,因此,只有當(dāng) "aaa" 位于字符串的開(kāi)頭的時(shí)候,"^aaa" 才能匹配,點(diǎn)擊測(cè)試 比如:"aaa xxx xxx"。

??? 點(diǎn)擊測(cè)試 舉例2:表達(dá)式 "aaa$" 在匹配 "xxx aaa xxx" 時(shí),匹配結(jié)果是:失敗。因?yàn)?"$" 要求與字符串結(jié)束的地方匹配,因此,只有當(dāng) "aaa" 位于字符串的結(jié)尾的時(shí)候,"aaa$" 才能匹配,點(diǎn)擊測(cè)試 比如:"xxx xxx aaa"。

??? 點(diǎn)擊測(cè)試 舉例3:表達(dá)式 ".\b." 在匹配 "@@@abc" 時(shí),匹配結(jié)果是:成功;匹配到的內(nèi)容是:"@a";匹配到的位置是:開(kāi)始于2,結(jié)束于4。
??? 進(jìn)一步說(shuō)明:"\b" 與 "^" 和 "$" 類似,本身不匹配任何字符,但是它要求它在匹配結(jié)果中所處位置的左右兩邊,其中一邊是 "\w" 范圍,另一邊是 非"\w" 的范圍。

??? 點(diǎn)擊測(cè)試 舉例4:表達(dá)式 "\bend\b" 在匹配 "weekend,endfor,end" 時(shí),匹配結(jié)果是:成功;匹配到的內(nèi)容是:"end";匹配到的位置是:開(kāi)始于15,結(jié)束于18。

一些符號(hào)可以影響表達(dá)式內(nèi)部的子表達(dá)式之間的關(guān)系:

表達(dá)式 作用
| 左右兩邊表達(dá)式之間 "或" 關(guān)系,匹配左邊或者右邊
( ) (1). 在被修飾匹配次數(shù)的時(shí)候,括號(hào)中的表達(dá)式可以作為整體被修飾
(2). 取匹配結(jié)果的時(shí)候,括號(hào)中的表達(dá)式匹配到的內(nèi)容可以被單獨(dú)得到

點(diǎn)擊測(cè)試 舉例5:表達(dá)式 "Tom|Jack" 在匹配字符串 "I'm Tom, he is Jack" 時(shí),匹配結(jié)果是:成功;匹配到的內(nèi)容是:"Tom";匹配到的位置是:開(kāi)始于4,結(jié)束于7。匹配下一個(gè)時(shí),匹配結(jié)果是:成功;匹配到的內(nèi)容是:"Jack";匹配到的位置時(shí):開(kāi)始于15,結(jié)束于19。

??? 點(diǎn)擊測(cè)試 舉例6:表達(dá)式 "(go\s*)+" 在匹配 "Let's go go go!" 時(shí),匹配結(jié)果是:成功;匹配到內(nèi)容是:"go go go";匹配到的位置是:開(kāi)始于6,結(jié)束于14。

??? 點(diǎn)擊測(cè)試 舉例7:表達(dá)式 "(\d+\.?\d*)" 在匹配 "$10.9,¥20.5" 時(shí),匹配的結(jié)果是:成功;匹配到的內(nèi)容是:"¥20.5";匹配到的位置是:開(kāi)始于6,結(jié)束于10。單獨(dú)獲取括號(hào)范圍匹配到的內(nèi)容是:"20.5"。


2. 正則表達(dá)式中的一些高級(jí)規(guī)則

2.1 匹配次數(shù)中的貪婪與非貪婪

在使用修飾匹配次數(shù)的特殊符號(hào)時(shí),有幾種表示方法可以使同一個(gè)表達(dá)式能夠匹配不同的次數(shù),比如:"{m,n}", "{m,}", "?", "*", "+",具體匹配的次數(shù)隨被匹配的字符串而定。這種重復(fù)匹配不定次數(shù)的表達(dá)式在匹配過(guò)程中,總是盡可能多的匹配。比如,針對(duì)文本 "dxxxdxxxd",舉例如下:

表達(dá)式 匹配結(jié)果
點(diǎn)擊測(cè)試 (d)(\w+) "\w+" 將匹配第一個(gè) "d" 之后的所有字符 "xxxdxxxd"
點(diǎn)擊測(cè)試 (d)(\w+)(d) "\w+" 將匹配第一個(gè) "d" 和最后一個(gè) "d" 之間的所有字符 "xxxdxxx"。雖然 "\w+" 也能夠匹配上最后一個(gè) "d",但是為了使整個(gè)表達(dá)式匹配成功,"\w+" 可以 "讓出" 它本來(lái)能夠匹配的最后一個(gè) "d"

由此可見(jiàn),"\w+" 在匹配的時(shí)候,總是盡可能多的匹配符合它規(guī)則的字符。雖然第二個(gè)舉例中,它沒(méi)有匹配最后一個(gè) "d",但那也是為了讓整個(gè)表達(dá)式能夠匹配成功。同理,帶 "*" 和 "{m,n}" 的表達(dá)式都是盡可能地多匹配,帶 "?" 的表達(dá)式在可匹配可不匹配的時(shí)候,也是盡可能的 "要匹配"。這 種匹配原則就叫作 "貪婪" 模式 。

非貪婪模式:

??? 在修飾匹配次數(shù)的特殊符號(hào)后再加上一個(gè) "?" 號(hào),則可以使匹配次數(shù)不定的表達(dá)式盡可能少的匹配,使可匹配可不匹配的表達(dá)式,盡可能的 "不匹配"。這種匹配原則叫作 "非貪婪" 模式,也叫作 "勉強(qiáng)" 模式。如果少匹配就會(huì)導(dǎo)致整個(gè)表達(dá)式匹配失敗的時(shí)候,與貪婪模式類似,非貪婪模式會(huì)最小限度的再匹配一些,以使整個(gè)表達(dá)式匹配成功。舉例如下,針對(duì)文本 "dxxxdxxxd" 舉例:

表達(dá)式 匹配結(jié)果
點(diǎn)擊測(cè)試 (d)(\w+?) "\w+?" 將盡可能少的匹配第一個(gè) "d" 之后的字符,結(jié)果是:"\w+?" 只匹配了一個(gè) "x"
點(diǎn)擊測(cè)試 (d)(\w+?)(d) 為了讓整個(gè)表達(dá)式匹配成功,"\w+?" 不得不匹配 "xxx" 才可以讓后邊的 "d" 匹配,從而使整個(gè)表達(dá)式匹配成功。因此,結(jié)果是:"\w+?" 匹配 "xxx"

更多的情況,舉例如下:

??? 點(diǎn)擊測(cè)試 舉例1:表達(dá)式 "<td>(.*)</td>" 與字符串 "<td><p>aa</p></td> <td><p>bb</p></td>" 匹配時(shí),匹配的結(jié)果是:成功;匹配到的內(nèi)容是 "<td><p>aa</p></td> <td><p>bb</p></td>" 整個(gè)字符串, 表達(dá)式中的 "</td>" 將與字符串中最后一個(gè) "</td>" 匹配。

??? 點(diǎn)擊測(cè)試 舉例2:相比之下,表達(dá)式 "<td>(.*?)</td>" 匹配舉例1中同樣的字符串時(shí),將只得到 "<td><p>aa</p></td>", 再次匹配下一個(gè)時(shí),可以得到第二個(gè) "<td><p>bb</p></td>"。


2.2 反向引用 \1, \2...

表達(dá)式在匹配時(shí),表達(dá)式引擎會(huì)將小括號(hào) "( )" 包含的表達(dá)式所匹配到的字符串記錄下來(lái)。在獲取匹配結(jié)果的時(shí)候,小括號(hào)包含的表達(dá)式所匹配到的字符串可以單獨(dú)獲取。這一點(diǎn),在前面的舉例中,已經(jīng)多次展示了。在實(shí)際應(yīng)用場(chǎng)合中,當(dāng)用某種邊界來(lái)查找,而所要獲取的內(nèi)容又不包含邊界時(shí),必須使用小括號(hào)來(lái)指定所要的范圍。比如前面的 "<td>(.*?)</td>"。

??? 其實(shí),"小括號(hào)包含的表達(dá)式所匹配到的字符串" 不僅是在匹配結(jié)束后才可以使用,在匹配過(guò)程中也可以使用。表達(dá)式后邊的部分,可以引用前面 "括號(hào)內(nèi)的子匹配已經(jīng)匹配到的字符串"。引用方法是 "\" 加上一個(gè)數(shù)字。"\1" 引用第1對(duì)括號(hào)內(nèi)匹配到的字符串,"\2" 引用第2對(duì)括號(hào)內(nèi)匹配到的字符串……以此類推,如果一對(duì)括號(hào)內(nèi)包含另一對(duì)括號(hào),則外層的括號(hào)先排序號(hào)。換句話說(shuō),哪一對(duì)的左括號(hào) "(" 在前,那這一對(duì)就先排序號(hào)。

舉例如下:

??? 點(diǎn)擊測(cè)試 舉例1:表達(dá)式 "('|")(.*?)(\1)" 在匹配 " 'Hello', "World" " 時(shí),匹配結(jié)果是:成功;匹配到的內(nèi)容是:" 'Hello' "。再次匹配下一個(gè)時(shí),可以匹配到 " "World" "。

??? 點(diǎn)擊測(cè)試 舉例2:表達(dá)式 "(\w)\1{4,}" 在匹配 "aa bbbb abcdefg ccccc 111121111 999999999" 時(shí),匹配結(jié)果是:成功;匹配到的內(nèi)容是 "ccccc"。再次匹配下一個(gè)時(shí),將得到 999999999。這個(gè)表達(dá)式要求 "\w" 范圍的字符至少重復(fù)5次,點(diǎn)擊測(cè)試 注意與 "\w{5,}" 之間的區(qū)別。

??? 點(diǎn)擊測(cè)試 舉例3:表達(dá)式 "<(\w+)\s*(\w+(=('|").*?\4)?\s*)*>.*?</\1>" 在匹配 "<td id='td1' style="bgcolor:white"></td>" 時(shí),匹配結(jié)果是成功。如果 "<td>" 與 "</td>" 不配對(duì),則會(huì)匹配失敗;如果改成其他配對(duì),也可以匹配成功。


2.3 預(yù)搜索,不匹配;反向預(yù)搜索,不匹配

前面的章節(jié)中,我講到了幾個(gè)代表抽象意義的特殊符號(hào):"^","$","\b"。它們都有一個(gè)共同點(diǎn),那就是:它們本身不匹配任何字符,只是對(duì) "字符串的兩頭" 或者 "字符之間的縫隙" 附加了一個(gè)條件。理解到這個(gè)概念以后,本節(jié)將繼續(xù)介紹另外一種對(duì) "兩頭" 或者 "縫隙" 附加條件的,更加靈活的表示方法。

正向預(yù)搜索:"(?=xxxxx)","(?!xxxxx)"

??? 格式:"(?=xxxxx)",在被匹配的字符串中,它對(duì)所處的 "縫隙" 或者 "兩頭" 附加的條件是:所在縫隙的右側(cè),必須能夠匹配上 xxxxx 這部分的表達(dá)式。因?yàn)樗皇窃诖俗鳛檫@個(gè)縫隙上附加的條件,所以它并不影響后邊的表達(dá)式去真正匹配這個(gè)縫隙之后的字符。這就類似 "\b",本身不匹配任何字符。"\b" 只是將所在縫隙之前、之后的字符取來(lái)進(jìn)行了一下判斷,不會(huì)影響后邊的表達(dá)式來(lái)真正的匹配。

??? 點(diǎn)擊測(cè)試 舉例1:表達(dá)式 "Windows (?=NT|XP)" 在匹配 "Windows 98, Windows NT, Windows 2000" 時(shí),將只匹配 "Windows NT" 中的 "Windows ",其他的 "Windows " 字樣則不被匹配。

??? 點(diǎn)擊測(cè)試 舉例2:表達(dá)式 "(\w)((?=\1\1\1)(\1))+" 在匹配字符串 "aaa ffffff 999999999" 時(shí),將可以匹配6個(gè)"f"的前4個(gè),可以匹配9個(gè)"9"的前7個(gè)。這個(gè)表達(dá)式可以讀解成:重復(fù)4次以上的字母數(shù)字,則匹配其剩下最后2位之前的部分。當(dāng)然,這個(gè)表達(dá)式可以不這樣寫,在此的目的是作為演示之用。

格式:"(?!xxxxx)",所在縫隙的右側(cè),必須不能匹配 xxxxx 這部分表達(dá)式。

??? 點(diǎn)擊測(cè)試 舉例3:表達(dá)式 "((?!\bstop\b).)+" 在匹配 "fdjka ljfdl stop fjdsla fdj" 時(shí),將從頭一直匹配到 "stop" 之前的位置,如果字符串中沒(méi)有 "stop",則匹配整個(gè)字符串。

??? 點(diǎn)擊測(cè)試 舉例4:表達(dá)式 "do(?!\w)" 在匹配字符串 "done, do, dog" 時(shí),只能匹配 "do"。在本條舉例中,"do" 后邊使用 "(?!\w)" 和使用 "\b" 效果是一樣的。

反向預(yù)搜索:"(?<=xxxxx)","(?<!xxxxx)"

??? 這兩種格式的概念和正向預(yù)搜索是類似的,反向預(yù)搜索要求的條件是:所在縫隙的 "左側(cè)",兩種格式分別要求必須能夠匹配和必須不能夠匹配指定表達(dá)式,而不是去判斷右側(cè)。與 "正向預(yù)搜索" 一樣的是:它們都是對(duì)所在縫隙的一種附加條件,本身都不匹配任何字符。

??? 舉例5:表達(dá)式 "(?<=\d{4})\d+(?=\d{4})" 在匹配 "1234567890123456" 時(shí),將匹配除了前4個(gè)數(shù)字和后4個(gè)數(shù)字之外的中間8個(gè)數(shù)字。由于 JScript.RegExp 不支持反向預(yù)搜索,因此,本條舉例不能夠進(jìn)行演示。很多其他的引擎可以支持反向預(yù)搜索,比如:Java 1.4 以上的 java.util.regex 包,.NET 中System.Text.RegularExpressions 命名空間,以及本站推薦的最簡(jiǎn)單易用的 DEELX 正則引擎。

更多
  • 該日志由 于2017年12月13日發(fā)表在 未分類 分類下, 你可以發(fā)表評(píng)論,并在保留原文地址 及作者的情況下引用到你的網(wǎng)站或博客。
  • 本文鏈接: 精通正則表達(dá)式 java正則表達(dá)式經(jīng)典實(shí)例 | 幫助信息-動(dòng)天數(shù)據(jù)
  • 文章標(biāo)簽:
  • 版權(quán)所有: 幫助信息-動(dòng)天數(shù)據(jù)-轉(zhuǎn)載請(qǐng)標(biāo)明出處
  • 【上一篇】 【下一篇】

    0 Comments.

    發(fā)表評(píng)論