如何在Java API中使用正則表達(dá)式?很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。
一、正則表達(dá)式的理論基礎(chǔ)
1、普通字符的表示
我們說(shuō)正則表達(dá)式主要由普通字符和元字符組成,那么我們首先先看看普通字符該如何表示。大部分普通字符由字符本身即可表示,例如:'s','i','n','g','l','e'等。除此之外,也有一些特殊的表示方式。
以/0開(kāi)頭,后面緊跟1-3位數(shù)字,表示的是一個(gè)八進(jìn)制數(shù)。這個(gè)數(shù)的十進(jìn)制值對(duì)應(yīng)于ASCII編碼中的相應(yīng)字符。
以/x或者/X開(kāi)頭,后面緊跟兩位字符,表示的是一個(gè)十六進(jìn)制的數(shù)。該數(shù)的十進(jìn)制的值對(duì)應(yīng)于ASCII編碼中相應(yīng)的字符。
以/u開(kāi)頭,后面緊跟四位字符,表示一個(gè)Unicode編號(hào)。該編號(hào)對(duì)應(yīng)于Unicode字符集中的一個(gè)具體字符。
另外還有一些元字符,雖然它們具有特殊的含義,但是往往在某種特殊情況下,需要將這些元字符當(dāng)做普通字符使用,我們使用 '/'+元字符,表示轉(zhuǎn)移該元字符,此后該元字符將表示一個(gè)普通字符。例如:'//','/^',它們分別表示的是 '/'和 '^',不再具有特殊含義了。下面我們開(kāi)始逐漸介紹正則表達(dá)式語(yǔ)法中的元字符的特殊含義。
2、字符組匹配單個(gè)字符
我們用一對(duì)中括號(hào)([.....])表示字符組,整個(gè)字符組中會(huì)有多個(gè)字符位列其中,該字符組表示的含義是:匹配任意一個(gè)字符,該字符是位列字符組中的。例如: [single]
匹配的是字符's','i','n','g','l','e'中的任意一個(gè)字符。以上我們簡(jiǎn)單介紹了字符組的基本概念以及它所能匹配的內(nèi)容,其實(shí)有時(shí)候?yàn)榱吮硎鲞B續(xù)的字符,我們會(huì)結(jié)合元字符 '-' 一起來(lái)操作字符組。例如:[0123456789],匹配的是0到9之間的任意一個(gè)數(shù)字,對(duì)于這種情況我們可以選擇這樣來(lái)簡(jiǎn)化操作:[0-9]。其實(shí)兩者表述的含義是一樣的,為了簡(jiǎn)化起見(jiàn),如果遇到連續(xù)的字符表述,可以選擇使用元字符來(lái)簡(jiǎn)化。同樣的還有[a-z],它匹配任意一個(gè)小寫(xiě)字母。對(duì)于元字符 '-' 還需要說(shuō)明一點(diǎn)的是:該字符只有出現(xiàn)在兩個(gè)字符之間才具有特殊含義,單獨(dú)出現(xiàn)在字符組的所有字符之前或者之后只能表述普通字符 '-' 。下面介紹有關(guān)字符組的一些其他相關(guān)的元字符。
元字符 '^' 表示排除的意思,和元字符 '-' 類似,只有放在所有字符的最前面才具有特殊含義,否則只能表示普通字符。例如: [^1234]
,該字符組匹配一個(gè)字符,但是不是1或2或3或4。當(dāng)然, [c^yy]
,匹配的是四個(gè)普通字符,'c','^','y','y'。此外,需要注意一點(diǎn)的是,除了以上介紹的幾種元字符必須置放于指定位置上才能起作用以外,其余所有元字符在字符組中統(tǒng)統(tǒng)被視作普通字符,不再具有特殊含義。
除此之外,字符組還支持嵌套使用。例如: [0-9[a-z]]
,該字符組匹配一個(gè)數(shù)字或者一個(gè)字母。我們也可以使用&&加強(qiáng)限定規(guī)則。例如: [0-9&&[^0123]]
,該字符組匹配的是0到9之間任意一個(gè)數(shù)字,但是該數(shù)字不能是0到3中任意一個(gè),也就是只能匹配4到9之間任意一個(gè)數(shù)字。最后和字符組有關(guān)的內(nèi)容還是涉及一個(gè)預(yù)定義字符組,所謂預(yù)定義字符組就是對(duì)字符組的適當(dāng)封裝,對(duì)于一些簡(jiǎn)單的組合使用簡(jiǎn)介的調(diào)用方式。例如:
?\d:等同于字符組 [0-9],表示任意一個(gè)數(shù)字字符
?\w:較為常見(jiàn),等同于字符組[0-9a-zA-Z],表示任意一個(gè)world(單詞字符)
?\s:等同于[ \t\n\x0B\f\r]
,匹配的是一個(gè)空格字符(space)
當(dāng)然,它們也有相對(duì)應(yīng)的大寫(xiě)形式,但是表示的意思卻是截然相反的。
?\D:等同于[^0-9]
,表示一個(gè)任意非數(shù)字字符
?\W:等同于[^0-9a-zA-Z]
,表示任意一個(gè)非單詞字符,往往會(huì)是一些特殊符號(hào)
?\S:等同于[^\t\n\x0B\f\r]
,匹配一個(gè)任意非空格的字符
3、用于指定字符多次出現(xiàn)的量詞
所謂的量詞主要是三個(gè)元字符,它們主要用于指定量詞前面的字符在匹配時(shí)可以多次出現(xiàn),具體區(qū)別接下來(lái)會(huì)介紹。首先我們需要知道,這三個(gè)元字符是:+ ,*, ?。下面描述它們各自作用及相互之間的區(qū)別:
?+:該元字符指定位于元字符前面的普通字符可以出現(xiàn)一次或者多次。例如:se+cyy這個(gè)正則表達(dá)式,字符secyy,seeeecyy都是可以匹配的,但是scyy是不能匹配的,前面的字符是必須出現(xiàn)的。
?*:該元字符指定位于元字符前面的普通字符可以出現(xiàn)零次或多次。例如:
se*cyy
對(duì)于該正則表達(dá)式而言,secyy,seecyy都是可匹配的,并且scyy也是可以匹配的。這就是和元字符 + 的簡(jiǎn)單區(qū)別。
??:該元字符指定位于元字符前面的普通字符可以出現(xiàn)也可以不出現(xiàn),但是不能多次出現(xiàn)。例如:se?cyy,對(duì)于該正則表達(dá)式,secyy,scyy等都是可匹配的,但是seeeecyy則是不能匹配的。它指定你前面的一個(gè)字符要么出現(xiàn),要么不出現(xiàn),不允許多次出現(xiàn)。
在這里我們要申明一個(gè)誤區(qū),這里的三個(gè)元字符量詞作用的是緊鄰該元字符前面的一個(gè)字符,并不是作用與元字符前面所有的字符,這里是需要注意的,包括筆者當(dāng)初也都是誤以為此的。
以上我們介紹了簡(jiǎn)單量詞的概念,但是它們只能用于表示模糊的次數(shù)。可以出現(xiàn)多次,但是多次是多少卻沒(méi)有定論。對(duì)于要求字符出現(xiàn)精確次數(shù)的情況,我們可以使用通用量詞來(lái)解決。{m,n}是通用量詞的最基本形式,它指定前面的字符出現(xiàn)的次數(shù)在m到n之間。
看幾個(gè)例子:
?se{0,10}cyy
:其中e可以出現(xiàn)0-10次
?se{9}cyy
:其中e必須出現(xiàn)9次
?se{0,}cyy
:其中e可以出現(xiàn)0-無(wú)窮大次,等同于se*cyy。
4、分組劃分組別
在介紹分組之前,無(wú)論是使用量詞還是字符組都是針對(duì)的一個(gè)字符。而分組針對(duì)的就是一串字符,我們也可以對(duì)分組使用量詞,控制該分組出現(xiàn)的次數(shù)。我們使用()括號(hào)表示分組,例如:
sing(le)de(cyy
其中l(wèi)e和cyy分別是一個(gè)分組,對(duì)于一個(gè)完整的正則表達(dá)式,從頭開(kāi)始,每個(gè)分組都是有編號(hào)的,按照出現(xiàn)的次序,以1為基數(shù)遞增。至于為什么要有編號(hào),下文說(shuō)。對(duì)于分組我們依然是可以使用量詞控制其出現(xiàn)次數(shù)的,例如:
sing(le)+cccc:在該正則表達(dá)式中,分組le可以出現(xiàn)一次或者多次 sing(le)*cccc:在該正則表達(dá)式中,分組le可以出現(xiàn)零次或者多次
結(jié)合元字符 '| ',可以實(shí)現(xiàn)和字符組一樣的功效,例如:
(happy|cyy|single)
該正則表達(dá)式可以匹配三個(gè)字符子串,happy,cyy,single。但是這里需要注意的是,元字符 | 如果用于字符組中就不再具有特殊含義,將會(huì)被作為普通字符來(lái)匹配。(這一點(diǎn)其實(shí)在介紹字符組的時(shí)候已經(jīng)強(qiáng)調(diào)過(guò))
下面解決一個(gè)上文遺留問(wèn)題,分組的編號(hào)到底有什么作用。為分組編號(hào)其實(shí)是為了重新捕獲和使用分組,每個(gè)分組按照出現(xiàn)的次序從1開(kāi)始遞增,我們使用 +分組編號(hào)進(jìn)行引用。
例如:
<(\w+)>(.*)</\1>:該正則表達(dá)式等效于:<(\w+)>(.*)</\w+>
(\w+)表示任意個(gè)字符(字母或數(shù)字),(.*)表示任意的符號(hào),\1則引用了分組(\w+)。所以在這里,html中所有非單標(biāo)簽元素都是能匹配的。當(dāng)然,如果我們不想使用默認(rèn)的編號(hào)來(lái)引用分組,我們其實(shí)也是可以在定義分組的時(shí)候?yàn)榉纸M命名。為分組命名的語(yǔ)法格式為: (?<name>X)
,引用分組的語(yǔ)法格式為: \k<name>
。例如:
<(?<num1>a)>(.*)</\k<num1>>:等效于:<a>(.*)</a>
上述正則表達(dá)式定義了一個(gè)名為num1的分組,并后續(xù)進(jìn)行了引用。下面介紹正則表達(dá)式的最后一塊理論基礎(chǔ),邊界匹配。
5、邊界匹配
以上我們所介紹的所有內(nèi)容主要還是針對(duì)單個(gè)字符或者多個(gè)字符組成的分組,我們可以限制他們的出現(xiàn)次數(shù)以及出現(xiàn)位置等。但是其實(shí)在正則表達(dá)式中,我們也是可以限制邊界必須滿足某種條件的。主要涉及的元字符有:^, $, \A, \Z, \z和\b。
首先看元字符 ^ ,在字符組中,該元字符表示否定的意思,此處匹配正則表達(dá)式首部位置邊界。例如: ^abc
匹配一個(gè)以abc開(kāi)頭的字符串。
元字符 $匹配的字符串的尾部邊界,它規(guī)定被匹配的字符串必須以什么結(jié)束。例如:
abc$:dabc,abc,abc/n都是可匹配的
實(shí)際上,如果被匹配字符串是以指定字符結(jié)尾或者指定字符之后跟換行符,都是可匹配的。此處需要注意尾部邊界匹配時(shí)的表述格式。(不同于首部匹配)
\b匹配的是單詞邊界,所謂的單詞邊界指的就是:當(dāng)一邊是字符,一邊是非字符的時(shí)候,此處即為單詞邊界。也就是單詞結(jié)束的那個(gè)位置。還有一些邊界,例如:\A,\b,\Z等,各自匹配的邊界如下圖所示;
當(dāng)然,對(duì)于邊界匹配最通用的一種方式就是環(huán)視。它不局限于整個(gè)表達(dá)式的開(kāi)頭和結(jié)尾,它可以出現(xiàn)在表達(dá)式中的任何位置,既可以向前匹配,也可以向后匹配。主要分為以下四種情況:
?肯定順序環(huán)視:它要求表達(dá)式的右邊字符串必須滿足某種約定,語(yǔ)法(?=....)
。例如:single(?=cyy)
,字符e的右邊即為邊界并且要求必須為cyy,所以該表達(dá)式只能匹配singlecyy。
?否定順序環(huán)視:它要求表達(dá)式的右邊字符串必須不能滿足某種約定,和上一中情況是相反的,語(yǔ)法格式為:(?!...)。
?肯定逆序環(huán)視:它要求表達(dá)式的左邊必須滿足某種約束,語(yǔ)法格式為:(?<=...)
。
?否定逆序環(huán)視:它要求表達(dá)式的左邊必須不能滿足某種約束,語(yǔ)法格式為:(?<!...)
。(此處為了消除!在MarkDown編輯器中的特殊樣式,加了空格,望讀者注意)
雖然看起來(lái)有四種不同的環(huán)視類型,但是實(shí)際上分為兩種,一種是向左看,一種是向右看。以上有關(guān)正則表達(dá)式的基本內(nèi)容大致介紹完結(jié),下面主要看看如何在Java中驗(yàn)證我們上述的這些理論。
二、Java API對(duì)正則表達(dá)式的支持
在Java中,對(duì)正則表達(dá)式的支持,主要還是java.util.regex
這個(gè)包,我們常用的是其中的Pattern和Matcher這兩個(gè)類。其中Pattern綁定了一個(gè)正則表達(dá)式,也就是代表了一個(gè)規(guī)則,Matcher綁定了一個(gè)Pattern和一個(gè)被處理的字符串,我們可以利用Matcher中的一些方法來(lái)完成匹配工作。此外,Java中所有的正則表達(dá)式都是以字符串的形式出現(xiàn)的,所以自然離不開(kāi)String這個(gè)類,該類中的很多方法的參數(shù)都是基于正則表達(dá)式的,下文將詳細(xì)介紹。我們首先看Pattern這個(gè)類。
Pattern主要用于編譯一個(gè)正則表達(dá)式,也就是創(chuàng)建一個(gè)Pattern對(duì)象,該對(duì)象與實(shí)際的一個(gè)正則表達(dá)式想綁定,它僅僅代表一個(gè)規(guī)則,與實(shí)際要匹配的字符串無(wú)關(guān)。
例如:
String str = "//w"; Pattern p = Pattern.compile(str);
Pattern的compile方法將str這個(gè)正則表達(dá)式編譯成一種內(nèi)部結(jié)構(gòu),然后以Pattern實(shí)例的形式返回,至于這種內(nèi)部結(jié)構(gòu)是什么樣子的,此處暫時(shí)不涉及。我們只需要知道,此時(shí)返回的pattern實(shí)例是綁定了一個(gè)正則表達(dá)式的。當(dāng)然,Pattern還有一個(gè)compile重載,可顯式指定匹配模式。
public static Pattern compile(String regex, int flags) { return new Pattern(regex, flags); }
此處主要有四種匹配模式可選,單行模式,多行模式,無(wú)視大小寫(xiě)模式,無(wú)視元字符模式(該模式下,所有元字符將會(huì)失效)。各自對(duì)應(yīng)的常量:Pattern.DOTALL,Pattern.MULTILINE,Pattern.CASE_INSENSITIVE,Pattern.LITERAL。這些常量的值如下:
public static final int DOTALL = 0x20;(32) public static final int MULTILINE = 0x08;(8) public static final int CASE_INSENSITIVE = 0x02;(2) public static final int LITERAL = 0x10;(16)
當(dāng)然,我們沒(méi)必要記住他們各自所對(duì)應(yīng)的常量的值,在使用的時(shí)候直接調(diào)用它們的常量名即可。下面通過(guò)介紹String的幾個(gè)基本方法,了解正則表達(dá)式在Java中的基本使用情況。
首先我們看split方法,該方法用于分割字符串,返回一個(gè)String數(shù)組。
public String[] split(String regex, int limit)
第一個(gè)參數(shù)接受的是一個(gè)正則表達(dá)式,第二參數(shù)用于限定分割次數(shù)。其實(shí)從其源代碼中我們大致可以知曉該方法作用原理:首先利用indexOf方法找到分割符首次出現(xiàn)的位置,將該位置以前所有字符保存,拿到剩余子串的所有內(nèi)容,一樣的操作。最后得到的數(shù)組就是按照分隔符分割的結(jié)果。limit只不過(guò)強(qiáng)制限定了分割次數(shù),達(dá)到次數(shù)上限,即使后面仍有分隔符可匹配,也選擇放棄。(打包后面所有內(nèi)容為一個(gè)分組),看個(gè)例子:
public static void main(String [] args){ String str = "cyy,single.abc/https"; String[] results = str.split("[,./]"); for(String s : results){ System.out.print(s+" "); } }
輸出結(jié)果:cyy single abc https
此處有人可能會(huì)有疑問(wèn),說(shuō)好的Pattern和Matcher才是正則表達(dá)式的主要操作類,怎么沒(méi)見(jiàn)到他們。其實(shí)在split內(nèi)部調(diào)用的就是Pattern的相關(guān)方法。
return Pattern.compile(regex).split(this, limit);
這是String類中split方法的最后一行代碼,String中的split方法除了最后一行代碼,其余代碼處理的都是regex為普通單個(gè)字符的情況,而對(duì)于多個(gè)字符乃至包含元字符的時(shí)候都是由Pattern中split方法處理的,該方法中會(huì)創(chuàng)建Matcher類并調(diào)用其中find等方法進(jìn)行匹配查找,代碼量比較多,此處不再贅述。
下面看String的一個(gè)匹配校驗(yàn)的方法。
public boolean matches(String regex) { return Pattern.matches(regex, this); }
顯然,該方法內(nèi)部調(diào)用的是Pattern的matches方法,
public static boolean matches(String regex, CharSequence input) { Pattern p = Pattern.compile(regex); Matcher m = p.matcher(input); return m.matches(); }
這是一個(gè)非常標(biāo)準(zhǔn)的對(duì)正則表達(dá)式的處理流程,首先編譯(綁定)正則表達(dá)式字符串獲取Pattern實(shí)例,然后調(diào)用Pattern的matcher方法獲取Matcher實(shí)例,接著就可以利用Matcher實(shí)例完成大量工作。此處調(diào)用matches方法完成對(duì)已綁定的正則表達(dá)式和預(yù)處理字符串的匹配工作,返回值為boolean。
最后看String的ReplaceAll方法:
public String replaceAll(String regex, String replacement) { return Pattern.compile(regex).matcher(this).replaceAll(replacement); }
該方法實(shí)際上還是依賴的Matcher中的replaceAll方法,由于一個(gè)Matcher實(shí)例是同時(shí)綁定一個(gè)正則表達(dá)式和一個(gè)被匹配字符串的。所以在Matcher內(nèi)部的replaceAll方法在進(jìn)行搜索匹配的時(shí)候就無(wú)需傳入額外參數(shù)。具體代碼,大家可以自行查看,此處節(jié)約篇幅不再贅述。
三、常見(jiàn)正則表達(dá)式的案例
接下來(lái)我們主要從日常較為普遍使用的一些案例中來(lái)深刻理解上述所有內(nèi)容。
1、Email地址
通常我們的Email地址的格式主要是:
?3-18字符,可使用英文、數(shù)字、減號(hào)、點(diǎn)或下劃線
?必須以英文字母開(kāi)頭,必須以英文字母或數(shù)字結(jié)尾
?點(diǎn)、減號(hào)、下劃線不能連續(xù)出現(xiàn)兩次或兩次以上
以上是騰訊QQ郵箱的要求,相對(duì)而言已算是較為復(fù)雜,接下來(lái)我么看如何實(shí)現(xiàn)它。首先,第一條要求:
[-._a-z0-9A-Z]{3,18}
滿足第二條要求:
[a-zA-Z][-._a-z0-9A-Z]{1,16}/w
滿足第三個(gè)條件:
(?![-0-9a-zA-Z._]*(--|\.\.|__))[a-zA-Z][-._a-z0-9A-Z]{1,16}/w
至于最后一個(gè)條件的匹配,我們使用否定順序環(huán)視來(lái)實(shí)現(xiàn),它要求右邊界所有內(nèi)容不能是如下的形式:0個(gè)或者多個(gè)(英文、數(shù)字、減號(hào)、點(diǎn)或下劃線)加上兩個(gè)連續(xù)減號(hào)或者點(diǎn)或者下劃線。也就是說(shuō),右邊如果由多個(gè)字符或者一個(gè)減號(hào),點(diǎn)或者下劃線,那是沒(méi)事的,可一旦出現(xiàn)連續(xù)的減號(hào),點(diǎn)或者下劃線,那么就將立馬被否定順序環(huán)視匹配,進(jìn)而不滿足條件結(jié)束。
其實(shí)上述對(duì)郵箱用戶名的匹配算是比較嚴(yán)格的,一般用于匹配郵箱用戶名的正則表達(dá)式則沒(méi)這么嚴(yán)格,具體要求如下:
?由英文字母、數(shù)字、下劃線、減號(hào)、點(diǎn)號(hào)組成
?至少1位,不超過(guò)64位
?開(kāi)頭不能是減號(hào)、點(diǎn)號(hào)和下劃線
由于比較簡(jiǎn)單,此處直接寫(xiě)出結(jié)果:
[^-._][-._a-zA-Z0-9]{0,63}
2、手機(jī)號(hào)碼
在看一個(gè)手機(jī)號(hào)碼的正則表達(dá)式匹配情況,具體要求如下:
?中國(guó)的手機(jī)號(hào)碼都是11位數(shù)字
?目前手機(jī)號(hào)第1位都是1,第2位取值為3、4、5、7、8之一
最終的表述結(jié)果為:
1[34578][0-9]{9}
看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對(duì)創(chuàng)新互聯(lián)的支持。
當(dāng)前題目:如何在JavaAPI中使用正則表達(dá)式-創(chuàng)新互聯(lián)
文章轉(zhuǎn)載:http://www.chinadenli.net/article48/igpep.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供電子商務(wù)、App設(shè)計(jì)、App開(kāi)發(fā)、用戶體驗(yàn)、域名注冊(cè)、靜態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容