柚子快報邀請碼778899分享:【java-正則表達式學習】
柚子快報邀請碼778899分享:【java-正則表達式學習】
正則表達式學習
什么是正則表達式?
正則表達式是一組由字母和符號組成的特殊文本,它可以用來從文本中找出滿足你想要的格式的句子。
一個正則表達式是一種從左到右匹配主體字符串的模式。 “Regular expression”這個詞比較拗口,我們常使用縮寫的術(shù)語“regex”或“regexp”。 正則表達式可以從一個基礎(chǔ)字符串中根據(jù)一定的匹配模式替換文本中的字符串、驗證表單、提取字符串等等。
想象你正在寫一個應(yīng)用,然后你想設(shè)定一個用戶命名的規(guī)則,讓用戶名包含字符、數(shù)字、下劃線和連字符,以及限制字符的個數(shù),好讓名字看起來沒那么丑。 我們使用以下正則表達式來驗證一個用戶名:
以上的正則表達式可以接受 john_doe、jo-hn_doe、john12_as。 但不匹配Jo,因為它包含了大寫的字母而且太短了。
1. 基本匹配
正則表達式其實就是在執(zhí)行搜索時的格式,它由一些字母和數(shù)字組合而成。 例如:一個正則表達式 the,它表示一個規(guī)則:由字母t開始,接著是h,再接著是e。
"the" => The fat cat sat on the mat.
正則表達式123匹配字符串123。它逐個字符的與輸入的正則表達式做比較。
正則表達式是大小寫敏感的,所以The不會匹配the。
"The" => The fat cat sat on the mat.
2. 元字符
正則表達式主要依賴于元字符。 元字符不代表他們本身的字面意思,他們都有特殊的含義。一些元字符寫在方括號中的時候有一些特殊的意思。以下是一些元字符的介紹:
分類:
限定符選擇匹配符分組組合和反向一弄符特殊字符字符匹配符定位符
在java中 \\ 代表其他語言中的 \ . java中需要2個 \ \ 代表轉(zhuǎn)義
下表包含了元字符的完整列表以及它們在正則表達式上下文中的行為:
(此表格來自于菜鳥教程)
字符描述\將下一個字符標記為一個特殊字符、或一個原義字符、或一個 向后引用、或一個八進制轉(zhuǎn)義符。例如,‘n’ 匹配字符 “n”?!甛n’ 匹配一個換行符。序列 ‘\’ 匹配 “” 而 “(” 則匹配 “(”。^匹配輸入字符串的開始位置。如果設(shè)置了 RegExp 對象的 Multiline 屬性,^ 也匹配 ‘\n’ 或 ‘\r’ 之后的位置。$匹配輸入字符串的結(jié)束位置。如果設(shè)置了RegExp 對象的 Multiline 屬性,$ 也匹配 ‘\n’ 或 ‘\r’ 之前的位置。*匹配前面的子表達式零次或多次。例如,zo* 能匹配 “z” 以及 “zoo”。* 等價于{0,}。+匹配前面的子表達式一次或多次。例如,‘zo+’ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等價于 {1,}。?匹配前面的子表達式零次或一次。例如,“do(es)?” 可以匹配 “do” 或 “does” 。? 等價于 {0,1}。{n}n 是一個非負整數(shù)。匹配確定的 n 次。例如,‘o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的兩個 o。{n,}n 是一個非負整數(shù)。至少匹配n 次。例如,‘o{2,}’ 不能匹配 “Bob” 中的 ‘o’,但能匹配 “foooood” 中的所有 o。‘o{1,}’ 等價于 ‘o+’。‘o{0,}’ 則等價于 ‘o*’。{n,m}m 和 n 均為非負整數(shù),其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,“o{1,3}” 將匹配 “fooooood” 中的前三個 o?!畂{0,1}’ 等價于 ‘o?’。請注意在逗號和兩個數(shù)之間不能有空格。?當該字符緊跟在任何一個其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面時,匹配模式是非貪婪的。非貪婪模式盡可能少的匹配所搜索的字符串,而默認的貪婪模式則盡可能多的匹配所搜索的字符串。例如,對于字符串 “oooo”,‘o+?’ 將匹配單個 “o”,而 ‘o+’ 將匹配所有 ‘o’。.匹配除換行符(\n、\r)之外的任何單個字符。要匹配包括 ‘\n’ 在內(nèi)的任何字符,請使用像"(.|\n)"的模式。(pattern)匹配 pattern 并獲取這一匹配。所獲取的匹配可以從產(chǎn)生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中則使用 $0…$9 屬性。要匹配圓括號字符,請使用 ‘(’ 或 ‘)’。(?:pattern)匹配 pattern 但不獲取匹配結(jié)果,也就是說這是一個非獲取匹配,不進行存儲供以后使用。這在使用 “或” 字符 (|) 來組合一個模式的各個部分是很有用。例如, 'industr(?:y|ies) 就是一個比 ‘industry|industries’ 更簡略的表達式。(?=pattern)正向肯定預(yù)查(look ahead positive assert),在任何匹配pattern的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以后使用。例如,“Windows(?=95|98|NT|2000)“能匹配"Windows2000"中的"Windows”,但不能匹配"Windows3.1"中的"Windows”。預(yù)查不消耗字符,也就是說,在一個匹配發(fā)生后,在最后一次匹配之后立即開始下一次匹配的搜索,而不是從包含預(yù)查的字符之后開始。(?!pattern)正向否定預(yù)查(negative assert),在任何不匹配pattern的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以后使用。例如"Windows(?!95|98|NT|2000)“能匹配"Windows3.1"中的"Windows”,但不能匹配"Windows2000"中的"Windows"。預(yù)查不消耗字符,也就是說,在一個匹配發(fā)生后,在最后一次匹配之后立即開始下一次匹配的搜索,而不是從包含預(yù)查的字符之后開始。(?<=pattern)反向(look behind)肯定預(yù)查,與正向肯定預(yù)查類似,只是方向相反。例如,"`(?<=95(?
【\u0391-\uffe5】漢字的范圍.
【\num】
(c)(a)\2
在正則表達式 (c)(a)\2 中:
(c) 是一個捕獲組,匹配字符 “c”。(a) 是第二個捕獲組,匹配字符 “a”。\2 是一個反向引用,表示對第二個捕獲組 (a) 的引用。它將匹配前面捕獲的內(nèi)容,即字符 “a”。
因此,這個正則表達式將匹配由一個 “c”、一個 “a”,再跟著一個 “a” 的字符串,例如 “caa”。
2.1 點運算符 .
.是元字符中最簡單的例子。 .匹配任意單個字符,但不匹配換行符。 例如,表達式.ar匹配一個任意字符后面跟著是a和r的字符串。
".ar" => The car parked in the garage.
如果需要單獨的匹配這個點 “.” ,那么就需要轉(zhuǎn)義一下 \ \ . 來表示.
2.2 字符集
字符集也叫做字符類。 方括號用來指定一個字符集。 在方括號中使用連字符來指定字符集的范圍。 也就是[]內(nèi)是可以提供匹配的字符, 其中多個字符之間是或的關(guān)系 在方括號中的字符集不關(guān)心順序。 例如,表達式[Tt]he 匹配 the 和 The。
"[Tt]he" => The car parked in the garage.
方括號的句號就表示句號。 表達式 ar[.] 匹配 ar.字符串
"ar[.]" => A garage is a good place to park a car.
2.2.1 否定字符集
一般來說 ^ 表示一個字符串的開頭,但它用在一個方括號的開頭的時候,它表示這個字符集是否定的。 例如,表達式[^c]ar 匹配一個后面跟著ar的除了c的任意字符。
"[^c]ar" => The car parked in the garage.
2.3 重復次數(shù)
后面跟著元字符 +,* or ? 的,用來指定匹配子模式的次數(shù)。 這些元字符在不同的情況下有著不同的意思。
這個重復的次數(shù)是指這些符號前面的 1個字符而已. 而不是多個
如果是前面的所有的字符的話, 那么匹配的是 azaz 了 .
2.3.1 * 號
*號匹配 在*之前的字符出現(xiàn) >= 0次。 例如,表達式 a* 匹配0或更多個以a開頭的字符。表達式[a-z]* 匹配一行中所有以小寫字母開頭的字符串。
"[a-z]*" => The car parked in the garage #21.
*字符和.字符搭配可以匹配所有的字符.*。 *和表示匹配空格的符號\s連起來用,如表達式\s*cat\s*匹配0或更多個空格開頭和0或更多個空格結(jié)尾的cat字符串。
"\s*cat\s*" => The fat cat sat on the concatenation.
2.3.2 + 號
+號匹配+號之前的字符出現(xiàn) >=1 次。 例如表達式c.+t 匹配以首字母c開頭以t結(jié)尾,中間跟著至少一個字符的字符串。
"c.+t" => The fat cat sat on the mat.
"\s+cat\s+" => The fat cat sat on the concatenation.
2.3.3 ? 號
在正則表達式中元字符 ? 標記在符號前面的字符為可選,即出現(xiàn) 0 或 1 次。 例如,表達式 [T]?he 匹配字符串 he 和 The。
"[T]he" => The car is parked in the garage.
"[T]?he" => The car is parked in the garage.
2.4 {} 號
在正則表達式中 {} 是一個量詞,常用來限定一個或一組字符可以重復出現(xiàn)的次數(shù)。 例如, 表達式 [0-9]{2,3} 匹配最少 2 位最多 3 位 0~9 的數(shù)字。
"[0-9]{2,3}" => The number was 9.9997 but we rounded it off to 10.0.
我們可以省略第二個參數(shù)。 例如,[0-9]{2,} 匹配至少兩位 0~9 的數(shù)字。
"[0-9]{2,}" => The number was 9.9997 but we rounded it off to 10.0.
如果逗號也省略掉則表示重復固定的次數(shù)。 例如,[0-9]{3} 匹配3位數(shù)字
"[0-9]{3}" => The number was 9.9997 but we rounded it off to 10.0.
【注意】 沒有最多是3個的這種說法。 {, 3} 沒有這種的表示方法. idea也會提示報錯的.
貪婪與懶惰
當正則表達式中包含能接受重復的限定符時,通常的行為是(在使整個表達式能得到匹配的前提下)匹配盡可能多的字符??紤]這個表達式:a.*b,它將會匹配最長的以a開始,以b結(jié)束的字符串。如果用它來搜索aabab的話,它會匹配整個字符串a(chǎn)abab。這被稱為貪婪匹配。
有時,我們更需要懶惰匹配,也就是匹配盡可能少的字符。前面給出的限定符都可以被轉(zhuǎn)化為懶惰匹配模式,只要在它后面加上一個問號?。這樣.*?就意味著匹配任意數(shù)量的重復,但是在能使整個匹配成功的前提下使用最少的重復?,F(xiàn)在看看懶惰版的例子吧:
a.*?b匹配最短的,以a開始,以b結(jié)束的字符串。如果把它應(yīng)用于aabab的話,它會匹配aab(第一到第三個字符)和ab(第四到第五個字符)。
為什么第一個匹配是aab(第一到第三個字符)而不是ab(第二到第三個字符)?簡單地說,因為正則表達式有另一條規(guī)則,比懶惰/貪婪規(guī)則的優(yōu)先級更高:最先開始的匹配擁有最高的優(yōu)先權(quán)——The match that begins earliest wins。
懶惰限定符
代碼/語法說明*?重復任意次,但盡可能少重復+?重復1次或更多次,但盡可能少重復??重復0次或1次,但盡可能少重復{n,m}?重復n到m次,但盡可能少重復{n,}?重復n次以上,但盡可能少重復
eg1:
// 定義正則表達式
String regex = "a.*b";
// 創(chuàng)建 Pattern 對象
Pattern pattern = Pattern.compile(regex);
// 要匹配的字符串
String string = "ab ab ab bbbbbb";
結(jié)果:
第1組: ab ab ab bbbbbb
直接是匹配到了最長的部分去了.
使用這個限定符?
// 定義正則表達式
String regex = "a.*?b";
// 創(chuàng)建 Pattern 對象
Pattern pattern = Pattern.compile(regex);
// 要匹配的字符串
String string = "ab ab ab bbbbbb";
結(jié)果:
第1組: ab
第2組: ab
第3組: ab
按照最短匹配的方式去匹配了.
2.5 (...) 特征標群 / 分組
特征標群是一組寫在 (...) 中的子模式。(...) 中包含的內(nèi)容將會被看成一個整體,和數(shù)學中小括號( )的作用相同。例如, 表達式 (ab)* 匹配連續(xù)出現(xiàn) 0 或更多個 ab。如果沒有使用 (...) ,那么表達式 ab* 將匹配連續(xù)出現(xiàn) 0 或更多個 b 。再比如之前說的 {} 是用來表示前面一個字符出現(xiàn)指定次數(shù)。但如果在 {} 前加上特征標群 (...) 則表示整個標群內(nèi)的字符重復 N 次。
我們還可以在 () 中用或字符 | 表示或。例如,(c|g|p)ar 匹配 car 或 gar 或 par.
"(c|g|p)ar" => The car is parked in the garage.
() 對要匹配的字符進行分組.
每次 find() 都會更新groups[] 數(shù)組
group(0) 代表找到的整個分組
group(1) 代表找到額第1個分組
group(2) 代表找到額第2個分組
使用到的類是 jdk里面自帶的類. java.util包下的
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class RegexExample {
public static void main(String[] args) {
// 定義正則表達式
String regex = "([0-9]{0,3})([a-zA-Z])";
// 創(chuàng)建 Pattern 對象
Pattern pattern = Pattern.compile(regex);
// 要匹配的字符串
String string = "78a 3B 989";
// 創(chuàng)建 Matcher 對象
Matcher matcher = pattern.matcher(string);
// 檢查是否有匹配
// 此處的匹配是用來匹配整個字符串是否匹配這個正則表達式.
// boolean matches = matcher.matches(); // 返回 true 因為整個字符串符合正則表達式
// System.out.println("Matches: " + matches);
int count = 0;
/**
* matcher.find()
* 1. 根據(jù)指定的規(guī)則,定位滿足規(guī)則的子字符串
* 2. 找到后,將子字符串的開始的索引記錄到matcher對象屬性 int[] groups;
* 3. 同時記錄oldLast 的值為子字符串的結(jié)束的索引的值. 即下次執(zhí)行find()時,就從上次臊面的最后位置開始
*/
while (matcher.find()) {
// group(0) 代表的是整個匹配到的字符串, 包含第1,2組的結(jié)果
System.out.println(++count+" "+matcher.group(0)+"====");
// group(1) 則代表的是匹配到第1組
System.out.println(++count+" "+matcher.group(1)+"====");
// group(2) 則代表的是匹配到第2組
System.out.println(++count+" "+matcher.group(2)+"====");
}
}
}
整體匹配也可以用 Pattern.matches(String regex, CharSequence input) 方法
boolean matches = Pattern.matches("^1(3|4|5|8)\\d{9}", "13888888888");
/**
* 命名分組 ()()
* 可以給分組取名
* (?
*
*/
public class RegexExample5 {
public static void main(String[] args) {
// 定義正則表達式
String regex = "(?
// 創(chuàng)建 Pattern 對象
Pattern pattern = Pattern.compile(regex);
// 要匹配的字符串
String content = " cata hhhacat acataaaa";
// 創(chuàng)建 Matcher 對象
Matcher matcher = pattern.matcher(content);
int count = 1;
while (matcher.find()) {
// group(0) 代表的是整個匹配到的字符串, 包含第1,2組的結(jié)果
System.out.println(matcher.group(0));
System.out.println(" 第"+count+"組: "+" "+matcher.group("name1"));
System.out.println(" 第"+count+"組: "+" "+matcher.group("name2"));
count++;
}
}
}
2.5.2 特別分組
2.5.2.1 (?:pattern)
public class RegexExample6 {
public static void main(String[] args) {
// 定義正則表達式
String regex1 = "java之父|java學習|java正則";
String regex2 = "java(之父|學習|正則)";
String regex3 = "java(?:之父|學習|正則)";
// 創(chuàng)建 Pattern 對象
Pattern pattern = Pattern.compile(regex1);
// 要匹配的字符串
String content = "java之父 YSJ java學習計劃 java正則表達式";
// 創(chuàng)建 Matcher 對象
Matcher matcher = pattern.matcher(content);
int count = 1;
while (matcher.find()) {
// 非分組,不可以用group(1)
System.out.println(" 第"+count+"組: "+" "+matcher.group(0));
count++;
}
Pattern compile = Pattern.compile(regex2);
Matcher matcher1 = compile.matcher(content);
int num=1;
while (matcher1.find()){
System.out.println(" 第"+num+"組: "+" "+matcher1.group(0));
// 可以分組,用group(1)
System.out.println(" 第"+num+"組: "+" "+matcher1.group(1));
num++;
}
Pattern compile3 = Pattern.compile(regex3);
Matcher matcher3 = compile3.matcher(content);
num=1;
while (matcher3.find()){
System.out.println(" 第"+num+"組: "+" "+matcher3.group(0));
// 不可以分組,不能group(1)
//System.out.println(" 第"+num+"組: "+" "+matcher1.group(1));
num++;
}
}
}
2.5.2.2 (?=pattern)
只改變上面例子的第3個.
String regex3 = "java(?=之父|學習|正則)";
結(jié)果如下:
最后只是這個匹配到的結(jié)果是 只有公共部分. 后面的不同的部分沒有打印.
2.5.2.3 (?!pattern)
可以看到的是, 這個是與 (?=pattern) 這個完全是一個取反的結(jié)果.
2.6 | 或運算符
或運算符就表示或,用作判斷條件。
例如 (T|t)he|car 匹配 (T|t)he 或 car。
"(T|t)he|car" => The car is parked in the garage.
"(T|t)he|car" => The car is parked in the garage.
2.7 轉(zhuǎn)義特殊字符
反斜線 \ 在表達式中用于轉(zhuǎn)碼緊跟其后的字符。用于指定 { } [ ] / \ + * . $ ^ | ? 這些特殊字符。如果想要匹配這些特殊字符則要在其前面加上反斜線 \。
例如 . 是用來匹配除換行符外的所有字符的。如果想要匹配句子中的 . 則要寫成 \. 以下這個例子 \.?是選擇性匹配.
"(f|c|m)at\.?" => The fat cat sat on the mat.
2.8 定位符
在正則表達式中,想要匹配指定開頭或結(jié)尾的字符串就要使用到錨點。^ 指定開頭,$ 指定結(jié)尾。
2.8.1 ^ 號
^ 用來檢查匹配的字符串是否在所匹配字符串的開頭。
例如,在 abc 中使用表達式 ^a 會得到結(jié)果 a。但如果使用 ^b 將匹配不到任何結(jié)果。因為在字符串 abc 中并不是以 b 開頭。
例如,^(T|t)he 匹配以 The 或 the 開頭的字符串。
"(T|t)he" => The car is parked in the garage.
"^(T|t)he" => The car is parked in the garage.
// 定義正則表達式
String regex = "[\\d]+[a-z]*";
// 創(chuàng)建 Pattern 對象
Pattern pattern = Pattern.compile(regex);
// 要匹配的字符串
String content = "a123abc";
// 創(chuàng)建 Matcher 對象
Matcher matcher = pattern.matcher(content);
int count = 1;
while (matcher.find()) {
// group(0) 代表的是整個匹配到的字符串, 包含第1,2組的結(jié)果
System.out.println(" 第"+count+"組: "+" "+matcher.group());
count++;
}
結(jié)果:
第1組: 123abc
可以看到目標是其中的片段 是可以匹配到的.
這個時候 加上 ^ 再試一次
String regex = "^[\\d]+[a-z]*";
這次就沒有匹配到了. 是因為不是以數(shù)字開頭的.
2.8.2 $ 指定結(jié)束符號
同理于 ^ 號,$ 號用來匹配字符是否是最后一個。
例如,(at\.)$ 匹配以 at. 結(jié)尾的字符串。
"(at\.)" => The fat cat. sat. on the mat.
2.8.3 \\b 指定邊界
示例 cat\\b 代表的是 目標字符串中包含有 cat結(jié)尾的
String regex = "cat\\b";
String content = "bacat cata hhhacat";
輸出結(jié)果:
第1組: cat
第2組: cat
2.8.3 \\B 指定邊界
與 \\b 相反, 以 示例 cat\\b 代表的是 目標字符串中包含有 cat開頭的 或者處于中間部位的.
3. 簡寫字符集
正則表達式提供一些常用的字符集簡寫。如下:
簡寫描述.除換行符外的所有字符\w匹配所有字母數(shù)字和下劃線,等同于 [a-zA-Z0-9_]\W匹配所有非字母數(shù)字,即符號,等同于: [^\w] , \w 取反\d匹配數(shù)字: [0-9]\D匹配非數(shù)字: [^\d]\s匹配所有空格字符,等同于: [\t\n\f\r\p{Z}]\S匹配所有非空格字符: [^\s]\f匹配一個換頁符\n匹配一個換行符\r匹配一個回車符\t匹配一個制表符\v匹配一個垂直制表符\p匹配 CR/LF(等同于 \r\n),用來匹配 DOS 行終止符
4. 零寬度斷言(前后預(yù)查)
先行斷言和后發(fā)斷言(合稱 lookaround)都屬于非捕獲組(用于匹配模式,但不包括在匹配列表中)。當我們需要一個模式的前面或后面有另一個特定的模式時,就可以使用它們。
例如,我們希望從下面的輸入字符串 $4.44 和 $10.88 中獲得所有以 $ 字符開頭的數(shù)字,我們將使用以下的正則表達式 (?<=\$)[0-9\.]*。意思是:獲取所有包含 . 并且前面是 $ 的數(shù)字。
零寬度斷言如下:
符號描述?=正先行斷言-存在?!負先行斷言-排除?<=正后發(fā)斷言-存在?
4.1 ?=... 正先行斷言
?=... 正先行斷言,表示第一部分表達式之后必須跟著 ?=...定義的表達式。
返回結(jié)果只包含滿足匹配條件的第一部分表達式。 定義一個正先行斷言要使用 ()。在括號內(nèi)部使用一個問號和等號: (?=...)。
正先行斷言的內(nèi)容寫在括號中的等號后面。 例如,表達式 (T|t)he(?=\sfat) 匹配 The 和 the,在括號中我們又定義了正先行斷言 (?=\sfat) ,即 The 和 the 后面緊跟著 (空格)fat。
"(T|t)he(?=\sfat)" => The fat cat sat on the mat.
"(T|t)he(?=\sfat)" => The fat cat sat on the mat.
4.2 ?!... 負先行斷言
負先行斷言 ?! 用于篩選所有匹配結(jié)果,篩選條件為 其后不跟隨著斷言中定義的格式。 正先行斷言 定義和 負先行斷言 一樣,區(qū)別就是 = 替換成 ! 也就是 (?!...)。
表達式 (T|t)he(?!\sfat) 匹配 The 和 the,且其后不跟著 (空格)fat。
"(T|t)he(?!\sfat)" => The fat cat sat on the mat.
"(T|t)he(?!\sfat)" => The fat cat sat on the mat.
4.3 ?<= ... 正后發(fā)斷言
正后發(fā)斷言 記作(?<=...) 用于篩選所有匹配結(jié)果,篩選條件為 其前跟隨著斷言中定義的格式。 例如,表達式 (?<=(T|t)he\s)(fat|mat) 匹配 fat 和 mat,且其前跟著 The 或 the。
"(?<=(T|t)he\s)(fat|mat)" => The fat cat sat on the mat.
"(?<=(T|t)he\s)(fat|mat)" => The fat cat sat on the mat.
4.4 ?
負后發(fā)斷言 記作 (?
"(? The cat sat on cat.
"(? The cat sat on cat.
5. 標志
標志也叫模式修正符,因為它可以用來修改表達式的搜索結(jié)果。 這些標志可以任意的組合使用,它也是整個正則表達式的一部分。
標志描述i忽略大小寫。g全局搜索。m多行修飾符:錨點元字符 ^ $ 工作范圍在每行的起始。
5.1 忽略大小寫
修飾語 i 用于忽略大小寫。 (insensitive) 不敏感 例如,表達式 /The/gi 表示在全局搜索 The,在后面的 i 將其條件修改為忽略大小寫,則變成搜索 the 和 The,g 表示全局搜索。
"The" => The fat cat sat on the mat.
"/The/gi" => The fat cat sat on the mat.
(?i)abc 表示abc都不區(qū)分大小寫
a(?i)bc 表示bc不區(qū)分大小寫
a((?i)b)c 表示只有b不區(qū)分大小寫
5.2 全局搜索
修飾符 g 常用于執(zhí)行一個全局搜索匹配,即(不僅僅返回第一個匹配的,而是返回全部)。 例如,表達式 /.(at)/g 表示搜索 任意字符(除了換行)+ at,并返回全部結(jié)果。
"/.(at)/" => The fat cat sat on the mat.
"/.(at)/g" => The fat cat sat on the mat.
5.3 多行修飾符
多行修飾符 m 常用于執(zhí)行一個多行匹配。
像之前介紹的 (^,$) 用于檢查格式是否是在待檢測字符串的開頭或結(jié)尾。但我們?nèi)绻胍诿啃械拈_頭和結(jié)尾生效,我們需要用到多行修飾符 m。
例如,表達式 /at(.)?$/gm 表示小寫字符 a 后跟小寫字符 t ,末尾可選除換行符外任意字符。根據(jù) m 修飾符,現(xiàn)在表達式匹配每行的結(jié)尾。
"/.at(.)?$/" => The fat
cat sat
on the mat.
"/.at(.)?$/gm" => The fat
cat sat
on the mat.
6. 貪婪匹配與惰性匹配
正則表達式默認采用貪婪匹配模式,在該模式下意味著會匹配盡可能長的子串。我們可以使用 ? 將貪婪匹配模式轉(zhuǎn)化為惰性匹配模式。
"/(.*at)/" => The fat cat sat on the mat.
"/(.*?at)/" => The fat cat sat on the mat.
8. java 相關(guān)類
Matcher
其他
13|14|15 到底是什么樣的組合呢? 是 1(3|1)(4|1)5 這個組合 還是 (13)|(14)|(15) 這個組合呢 ? 這個我感覺應(yīng)該是牽扯到運算符的優(yōu)先級
13|14|15
如果是 ①: 1(3|1)(4|1)5 , 那么就是無符號的優(yōu)先級要低于 | , 也就是 1115應(yīng)該是一個匹配項. 可以看到的是 只是匹配到了這個 15 . 并沒有整體匹配上,那也就是第②種了. (13)|(14)|(15) 是這個組合了, 13 或者 14 或者 15 . 測試如下
字符具有高于替換運算符的優(yōu)先級,使得"m|food"匹配"m"或"food"。若要匹配"mood"或"food",請使用括號創(chuàng)建子表達式,從而產(chǎn)生"(m|f)ood"。
從別的地方找的.
9. 使用正則表達式表示數(shù)字范圍
表示0-9
[0-9]
表示0-99 直接用 \d{0,2} 是不對的, 因為00 , 09也會被匹配到.
[0-9]|[1-9]\d
表示0-999
[0-9]|[1-9]\d|[1-9]\d{2}
表示 0-255
^([0-9]|[1-9]\d|[1-2][0-5][0-5])$
表示 >=0 且 <= 2147483647的數(shù)(最多2位小數(shù)) , 同事的一個問題… 難死了 . 我們分2種情況吧, 簡略一下這個長度. 2147483647 (10位) ① 只有整數(shù) 也就是 0<= num <= 2147483647 的整數(shù) 我們把這個范圍 拆一下: 0-999999999 (9位) + 1000000000-2147483647
0-9: [0-9]
10-99: [1-9]\d
100-999: [1-9]\d{2}
1000-9999:[1-9]\d{3}
10000-99999: [1-9]\d{4}
100000-999999: [1-9]\d{5}
1000000-9999999: [1-9]\d{6}
10000000-99999999: [1-9]\d{7}
100000000-999999999: [1-9]\d{8}
1000000000-2147483647
[1-2][0-1][0-4][0-7][0-4][0-8][0-3][0-6][0-4][0-7]
開始拼接:
^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-9]\d{4}|[1-9]\d{5}|[1-9]\d{6}|[1-9]\d{7}|[1-9]\d{8}|[1-2][0-1][0-4][0-7][0-4][0-8][0-3][0-6][0-4][0-6])$
略長. 再拼接上后面的小數(shù)部分
[.][\d]{1,2}
再考慮到 不可以大于 2147483647 所以是 0-2147483646.99 2147483647.0 2147483647.00
最后結(jié)果: ^((([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-9]\d{4}|[1-9]\d{5}|[1-9]\d{6}|[1-9]\d{7}|[1-9]\d{8}|[1-2][0-1][0-4][0-7][0-4][0-8][0-3][0-6][0-4][0-6])([.]\d{1,2})?)|2147483647|2147483647[.][0]{1,2})$
測試: 驗證通過~~
其中這個整數(shù)部分看著太長了, 優(yōu)化一下. 0-999999999 (9位)
^([1-9]\d{0,8}|0)$
這樣就短了很多了, 再拼接上后面的.
^((([1-9]\d{0,8}|0|[1-2][0-1][0-4][0-7][0-4][0-8][0-3][0-6][0-4][0-6])([.]\d{1,2})?)|2147483647|2147483647[.][0]{1,2})$
10. 練習
1.驗證是漢字
^[\u0391-\uffe5]*$
2.驗證郵政編碼 . 非0開頭, 可0結(jié)束
^[1-9]\d{5}$
3.QQ號, 要求是 1-9 開頭的5-10位的數(shù)字
^[1-9]\d{4,9}$
4.手機號碼: 要求是必須以 13 14 15 18 開頭的11數(shù)字
第一種:
^1(3|4|5|8)\d{9}$
第二種:
^1[3458]\d{9}$
第三種:
^(13|14|15|18)\d{9}$
5.驗證URL
^((http|https)://)([\w-]+\.)+[\w-]+(\/[\w-?=&/%.#]*)?$
【注意】 [ ] 內(nèi)部是什么就匹配什么不需要轉(zhuǎn)義
6.使用反向引用去重
public static void main(String[] args) {
// 定義正則表達式
String regex = "(.)\\1+";
// 要匹配的字符串
String content = "我我要要要學編程";
// 創(chuàng)建 Pattern 對象
String res = Pattern.compile(regex).matcher(content).replaceAll("$1"); // 用一個去替換多個
System.out.println(res);
}
我要學編程
零零散散一天就學了個這… 太慢了
?
?
?
?
?
柚子快報邀請碼778899分享:【java-正則表達式學習】
相關(guān)鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。