正則表達式是一個很是強大的字符串處理工具,經過一種特殊的語法來描述一種模式,再經過模式能夠完成字符串的匹配,萃取,替換等操做java
要判斷一個字符串是不是一個郵箱,可能須要不少的判斷邏輯,使用則表達式,只須要下面代碼便可git
Pattern pattern = Pattern.compile("^([a-z0-9._%+-]+)@([a-z0-9.-]+)\\.[a-z]{2,4}$"); Matcher matcher = pattern.matcher("hatlonely@foxmail.com"); assertTrue(matcher.matches());
主要有 Pattern
對象和 Matcher
對象github
Pattern
: 模式對象Matcher
: 匹配的結果Matcher
提供 matches
方法用於徹底匹配,find
方法用於部分匹配,還提供 asPredicate
方法返回一個部分匹配的謂詞正則表達式
Pattern
提供一個靜態方法 matches
用於徹底匹配,這個方法會臨時構造 Pattern
對象,若是 Pattern
會被屢次重複使用,儘可能別直接使用這種方法工具
assertTrue(Pattern.compile("hello").matcher("hello").matches()); // 徹底匹配 assertTrue(Pattern.compile("hello").matcher("hello world").find()); // 部分匹配 assertTrue(Pattern.compile("hello").asPredicate().test("hello world")); // 部分匹配 assertTrue(Pattern.matches("hello", "hello")); // 徹底匹配
符號 | 含義 |
---|---|
c |
匹配單個字符 c |
. |
匹配全部單個字符,換行符 \n 除外 |
^ |
匹配字符串開始 |
$ |
匹配字符串結束 |
\b |
匹配字符界,字符和空白之間 |
\B |
匹配非字符界,字符和空白之間 |
| | 匹配前面表達式或者後面表達式 |
[charset] |
匹配任意括號內的字符,可用 - 表示範圍,[a-z] 表示全部小寫字母 |
[^charset] |
匹配任意括號外的字符 |
\d |
匹配數字,至關於 [0-9] |
\D |
匹配非數字,至關於 1 |
\s |
匹配空白符,至關於 [ fnrtv] |
\S |
匹配非空白符,至關於 2 |
\f |
匹配換頁符 |
\n |
匹配換行符 |
\r |
匹配回車 |
\t |
匹配字表符 |
\v |
匹配垂直製表符 |
\w |
匹配字符類字符,包括下劃線,至關於 [A-Za-z0-9_] |
\W |
匹配非字符類字符,3 |
\u |
匹配四位十六進制數表示的 Unicode 字符,\u00A9 例如匹配 © |
\x |
匹配兩位十六進制數表示的 ascii 碼 |
限定符 | 含義 |
---|---|
* |
匹配前面字符或表達式 0 次或屢次 |
+ |
匹配前面字符或表達式 1 次或屢次 |
? |
匹配前面字符或表達式 0 次或1次,跟着其餘限定詞後表示非貪婪匹配 |
{n} |
匹配前面字符或表達式 n 次 |
{n,} |
匹配前面字符或表達式至少 n 次 |
{n,m} |
匹配前面字符或表達式至少 n 次,至多 m 次 |
assertTrue(Pattern.matches("[0-9]*", "")); assertTrue(Pattern.matches("[0-9]?", "")); assertTrue(Pattern.matches("[0-9]?", "1")); assertTrue(Pattern.matches("[0-9]+", "123")); assertTrue(Pattern.matches("[0-9]{3}", "123")); assertTrue(Pattern.matches("[0-9]{3,4}", "123")); assertTrue(Pattern.matches("[0-9]{3,4}", "1234")); assertTrue(Pattern.matches("[0-9]{3,}", "1234")); assertTrue(Pattern.matches("\\d+", "123")); assertTrue(Pattern.matches("\\s+", " \t")); assertTrue(Pattern.matches("\\w+", "abc")); assertTrue(Pattern.matches("(f|z)oo", "foo")); assertTrue(Pattern.matches("(f|z)oo", "zoo")); assertTrue(Pattern.matches(".*", "any string"));
支持用小括號 ()
將模式分組,Matcher
提供 group
方法獲取分組的內容測試
符號 | 含義 |
---|---|
(pattern) |
匹配分組而且捕獲子表達式 |
(?:pattern) |
匹配分組可是不捕獲子表達式 |
使用 groupCount
獲取捕獲分組的數量,因爲下面例子中模式串中沒有小括號,因此沒有捕獲的分組code
Pattern pattern = Pattern.compile("^[a-z0-9]+@[a-z0-9.]+[.][a-z]{2,4}$"); Matcher matcher = pattern.matcher("hatlonely@foxmail.com"); assertTrue(matcher.matches()); assertEquals(matcher.groupCount(), 0);
使用 group
方法獲取分組的內容,分組的編號以左括號爲準,gruop(i)
返回第 i
個分組,group(0)
表明整個匹配串對象
Pattern pattern = Pattern.compile("^([a-z0-9]+)@(([a-z0-9.]+)[.]([a-z]{2,4}))$"); Matcher matcher = pattern.matcher("hatlonely@foxmail.com"); assertTrue(matcher.matches()); assertEquals(matcher.groupCount(), 4); assertEquals(matcher.group(), "hatlonely@foxmail.com"); assertEquals(matcher.group(1), "hatlonely"); assertEquals(matcher.group(2), "foxmail.com"); assertEquals(matcher.group(3), "foxmail"); assertEquals(matcher.group(4), "com");
能夠用 ?:
阻止捕獲,以下面代碼所示,foxmail.com
就沒有被捕獲ci
Pattern pattern = Pattern.compile("^([a-z0-9]+)@(?:([a-z0-9.]+)[.]([a-z]{2,4}))$"); Matcher matcher = pattern.matcher("hatlonely@foxmail.com"); assertTrue(matcher.matches()); assertEquals(matcher.groupCount(), 3); assertEquals(matcher.group(), "hatlonely@foxmail.com"); assertEquals(matcher.group(0), "hatlonely@foxmail.com"); assertEquals(matcher.group(1), "hatlonely"); assertEquals(matcher.group(2), "foxmail"); assertEquals(matcher.group(3), "com");
符號 | 含義 |
---|---|
(?=pattern) |
正向預測,非捕獲匹配,匹配結束 |
(?!pattern) |
反向預測,非捕獲匹配,匹配結束 |
(?<=pattern) |
正向預測,非捕獲匹配,匹配開始 |
(?<!pattern) |
反向預測,非捕獲匹配,匹配開始 |
正向預測是指匹配開始或者結束的字符串須要匹配(或者反向預測不能匹配)分組,分組內的模式僅用於預測,不會出如今最終的匹配串中,這種匹配只能用於部分匹配,?=
,?!
匹配開始,?<=
,?<!
匹配結束字符串
{ Pattern pattern = Pattern.compile("Windows (?=95|98|NT|2000)"); Matcher matcher = pattern.matcher("Windows 2000"); assertTrue(matcher.find()); assertEquals(matcher.group(), "Windows "); assertEquals(matcher.groupCount(), 0); } { Pattern pattern = Pattern.compile("Windows (?!95|98|NT|2000)"); Matcher matcher = pattern.matcher("Windows vista"); assertTrue(matcher.find()); assertEquals(matcher.group(), "Windows "); assertEquals(matcher.groupCount(), 0); } { Pattern pattern = Pattern.compile("(?<=95|98|NT|2000) Windows"); Matcher matcher = pattern.matcher("2000 Windows"); assertTrue(matcher.find()); assertEquals(matcher.group(), " Windows"); assertEquals(matcher.groupCount(), 0); } { Pattern pattern = Pattern.compile("(?<!95|98|NT|2000) Windows"); Matcher matcher = pattern.matcher("vista Windows"); assertTrue(matcher.find()); assertEquals(matcher.group(), " Windows"); assertEquals(matcher.groupCount(), 0); }
符號 | 含義 |
---|---|
\1 |
匹配捕獲匹配到的反向引用,\2 表示第二個反向引用 |
前面經過捕獲得到的分組能夠再後面引用,好比 (\w+) \1
表示兩個重複的單詞
assertTrue(Pattern.matches("(\\w+) \\1", "ab ab")); assertTrue(Pattern.matches("(\\w+) \\1", "abc abc")); assertFalse(Pattern.matches("(\\w+) \\1", "abc def"));
String
和 Pattern
都提供了 replaceAll
和 replaceFirst
方法來做正則替換,替換串中能夠 $i
來獲取正則匹配捕獲的分組
Pattern pattern = Pattern.compile("^([a-z0-9]+)@(?:([a-z0-9.]+)[.]([a-z]{2,4}))$"); assertEquals(pattern.matcher("hatlonely@foxmail.com").replaceAll( "$0 $1 $2 $3" ), "hatlonely@foxmail.com hatlonely foxmail com"); assertEquals("hatlonely@foxmail.com".replaceAll( "^([a-z0-9]+)@(?:([a-z0-9.]+)[.]([a-z]{2,4}))$", "$0 $1 $2 $3" ), "hatlonely@foxmail.com hatlonely foxmail com");
每次 find 調用都會匹配目標串中的一個匹配,經過屢次 find
調用,能夠找出目標串中全部的匹配
String str = "abab x acac y aeae"; Pattern pattern = Pattern.compile("(\\w+)\\1"); Matcher matcher = pattern.matcher(str); List<String> li = new ArrayList<>(); while (matcher.find()) { li.add(matcher.group()); assertThat(str.substring(matcher.start(), matcher.end()), equalTo(matcher.group())); } assertThat(li, equalTo(List.of("abab", "acac", "aeae")));