正則表達式入門
[提前聲明]
文章由作者:張耀峯 結合自己生產中的使用經驗整理,最終形成簡單易懂的文章
寫作不易,轉載請註明,謝謝!
大數據代碼案例地址: https://github.com/Mydreamandreality/sparkResearch
正則表達式
- 正則表達式在後端開發中可以說是必備技能之一:數據過濾、數據校驗、數據轉換等等場景都會用到正則表達式,所以在這兒就分享一下正則表達式的基本入門,以及在Java中如何使用正則表達式
元字符
元字符是構造正則表達式的一種基本元素
元字符 | 說明 |
---|---|
. | 匹配除了換行符之外的所有字符 |
\w | 匹配字母或數字或下劃線或漢字 |
\s | 匹配任意的空白符 |
\d | 匹配數字 |
\b | 匹配單詞的開始或者結束 |
^ | 匹配字符串的開始 |
$ | 匹配字符串的結束 |
案例:
匹配abc開頭的字符串
^abc
\babc
匹配11位手機號
^\d\d\d\d\d\d\d\d\d\d\d$
匹配11位手機號,1開頭的
^1\d\d\d\d\d\d\d\d\d\d$
重複限定符
有了元字符就可以寫不少的正則表達式了,但是這樣寫太原始了,看着有些亂,正則沒提供辦法處理這些重複的元字符嗎?
答案是有的!爲了處理這些重複問題,正則表達式中一些重複限定符,把重複部分用合適的限定符替代,下面我們來看一些限定符:
語法 | 說明 |
---|---|
* | 重複零次或者更多次 |
+ | 重複一次或者更多次 |
? | 重複0次或者1次 |
{n} | 重複n次 |
{n,} | 重複n次或者更多次 |
{n,m} | 重複n到m次 |
案例改造:
匹配abc開頭的字符串
^abc
\babc
匹配11位手機號
^\d{11}$
匹配11位手機號,1開頭的
^1\d{10}$
匹配a開頭的,0個或者多個b結尾的字符串
^ab*$
分組
從上面的例子中看到,* 限定符是作用在與他左邊最近的一個字符,那麼問題來了,如果我想要ab同時被*限定那怎麼辦呢?
匹配字符串中包含0到多個ab開頭:
^(ab)*
轉義
正則表達式用小括號來做分組,那麼問題來了:
如果要匹配的字符串中本身就包含小括號,那是不是衝突?應該怎麼辦?
針對這種情況,正則提供了轉義的方式,也就是要把這些元字符、限定符或者關鍵字轉義成普通的字符,做法很簡答,就是在要轉義的字符前面加個斜槓,也就是\即可。
如:要匹配以(ab)開頭:
^(\(ab\))*
條件或
回到我們剛纔的手機號匹配,我們都知道:國內號碼都來自三大網,它們都有屬於自己的號段,比如聯通有130/131/132/155/156/185/186/145/176等號段,假如讓我們匹配一個聯通的號碼,那按照我們目前所學到的正則,應該無從下手的,因爲這裏包含了一些並列的條件,也就是“或”,那麼在正則中是如何表示“或”的呢?
正則用符號 | 來表示或,也叫做分支條件,當滿足正則裏的分支條件的任何一種條件時,都會當成是匹配成功
那麼我們就可以用或條件來處理這個問題
^(130|131|132|155|156|185|186|145|176)\d{8}$
區間
看到上面的例子,是不是看到有什麼規律?是不是還有一種想要簡化的衝動?實際是有的
正則提供一個元字符中括號 [] 來表示區間條件。
限定0到9 可以寫成[0-9]
限定A-Z 寫成[A-Z]
限定某些數字 [165]
優化正則
^((13[0-2])|(15[56])|(18[5-6])|145|176)\d{8}$
現在你已經基本瞭解正則表達式的構成和使用,下面我們演示如何在Java中使用正則表達式
Java中的正則表達式
在Java中要使用正則表達式,需要用到java.util.regex
類庫包
它是一個用正則表達式所定製的模式對字符串進行匹配工作
它包含兩個類:Pattern和Matcher
Pattern是一個正則表達式經過編譯後的表現模式
Matcher根據Pattern對象作爲匹配模式對字符串進行匹配
說白了就是Pattern定義正則表達式,Matcher根據定義的正則來過濾字符串
Pattern
Pattern的構造方法是私有的,不可以直接創建,需要使用靜態工廠模式創建:
Pattern.complie(String regex);
matcher
Matcher的構造方法也是私有的,不能直接創建,使用
Pattern.matcher(CharSequence input)
Java代碼示例
public static List<Integer> matcherNumber(String soap) {
final String regex = "\\d+";
Pattern pattern = Pattern.compile(regex);
Matcher m = pattern.matcher(soap);
...暫時先省略部分代碼
}
- matches 對所有字符串進行匹配,只有整個字符串都匹配才返回True
- lookingAt 對前面的字符串能進行匹配,匹配到的字符串在最前面返回True
- find 對字符串進行匹配,匹配到的字符串可以在任意的位置返回True
Matcher類提供三個匹配操作方法,三個方法均返回boolean類型,當匹配到時返回true,沒匹配到則返回false
- matches()代碼示例
Pattern p = Pattern.complie("\\d+");
Matcher m = p.matcher("123ddd");
m.matches(); //返回false
//解釋:
因爲matches要匹配整個字符串才返回true,而(\\d+)這個正則要匹配的是數字,所以文本(123ddd)中的ddd無法被匹配,故返回false
//------------------我是分割線------------------
Matcher m1 = p.matcher("123321");
m1.matches(); //返回true
//解釋:
文本(123321)可以被全部匹配,所以返回True
- lookingAt()代碼示例
Pattern p = Pattern.complie("\\d+");
Matcher m = p.matcher("ddd123");
m.lookingAt(); //返回false
//解釋:
因爲matches要匹配到字符串前綴,而(\\d+)這個正則要匹配的是數字,所以文本(ddd123)中的ddd前綴不是數字,無法被匹配,故返回false
//------------------我是分割線------------------
Matcher m1 = p.matcher("123ddd");
m1.lookingAt(); //返回true
//解釋:
文本(123ddd)前綴匹配成功,所以返回True
- find()代碼示例
Pattern p = Pattern.complie("\\d+");
Matcher m = p.matcher("ddd123");
m.find(); //返回true
//解釋:
在字符串任意位置匹配到了數字,所以返回true
//------------------我是分割線------------------
Matcher m1 = p.matcher("123ddd");
m1.find(); //返回true
//解釋:
在字符串任意位置匹配到了數字,所以返回true
當我們使用以上的匹配模式匹配到數據後,可以使用以下三個方法得到更詳細的信息
-
start() 返回匹配到的子字符串在字符串中的索引位置
-
end() 返回匹配到的子字符串的最後一個字符在字符串中的索引位置
-
group() 返回匹配到的子字符串
-
Java代碼示例
讓我們把前面的代碼案例補充完整
public static List<Integer> matcherNumber(String soap) {
final String regex = "\\d+";
Pattern pattern = Pattern.compile(regex);
Matcher m = pattern.matcher(soap);
List<Integer> result = new ArrayList();
while(m.find){
result.add(m.group());
}
return result;
}
//使用
matcherNumber(111aaa222bbb333ccc);
//返回輸出
List<111,222,333>
堅持看到這裏,相信你已經入門正則表達式,並且能夠在項目中使用了,正則的高級使用方法,後續如果有時間的話會繼續更新!