Java 正規表達式
正規表達式,聽起來有點陌生,但是幹我們這行的應該經常會用到,最常用的莫過于在搜尋了,我們經常會用Windows資料總管中搜尋某個同意字尾名的檔案,例如我們要找目前檔案夾下的所有java檔案,那麼就可以在資料總管的搜尋框中輸入“*.java”,又或者我們要搜尋檔案名以“Java”這個字元串開頭的檔案,我們就可以輸入“Java?”,這兩個例子中的”*”(星号)和”?”(問号)分别代表了“任意長度的任意字元”和”一個字元長度的任意字元”,但是正規表達式遠不止這兩個,接下來就來學習一些比較常用的正規表達式知識吧:
1. 正規表達式的作用
正規表達式是專門用于操作字元串,我們常用的搜尋和替換操作就是要求我們提供與預期的搜尋結果比對的确切字元串,雖然Java當中對字元串執行簡單搜尋和替換任務可能已經足夠了,但這樣缺乏靈活性,若采用正規表達式來做這些工作,效率和靈活性都會比較高了。正規表達式的用途有:
1) 比對字元串:
例如,可以測試輸入字元串,以檢視字元串内是否出現電話号碼模式或信用卡号碼模式。這稱為資料驗證。
2) 替換字元串:
可以使用正規表達式來識别文檔中的特定文本,完全删除該文本或者用其他文本替換它。
3) 切割字元串:
将文本按照一定的模式來分割成若幹子串。
4) 擷取字元串:
取出字元串中符合某個模式的子串。
優點:正規表達式可以簡化對字元串的複雜操作。
缺點:如果正規表達式寫的很複雜,可閱讀性就會非常差。
2. 正規表達式的基本文法
由于正規表達式的文法比較多,這裡隻列舉部分,詳細的正規表達式文法請點選這裡。
部分文法表格如下:
1) 字元比對文法:
字元文法 | 文法解釋 | 文法例子 |
\d | 比對數字(0~9) | ‘\d’比對8,不比對12; |
\D | 比對非數字 | ‘\D’比對c,不比對3; |
\w | 比對任意單字元 | ‘\w\w’ 比對A3,不比對@3; |
\W | 比對非單字元 | ‘\W’比對@,不比對c; |
\s | 比對空白字元 | ‘\d\s\d’比對3 d,不比對abc; |
\S | 比對非空字元 | ‘\S\S\S’比對A#4,不比對3 d; |
. | 比對任意字元 | ‘....’比對A$ 5,不比對換行; |
[…] | 比對括号中任意字元 | [b-d]比對b、c、d, 不比對e; |
[^…] | 比對非括号字元 | [^b-z]比對a,不比對b-z的字元; |
2) 重複比對文法:
重複文法 | 文法解釋 | 文法例子 |
{n} | 比對n次字元 | \d{3}比對\d\d\d,不比對\d\d或\d\d\d\d |
{n,} | 比對n次和n次以上 | \w{2}比對\w\w和\w\w\w以上,不比對\w |
{n,m} | 比對n次上m次下 | \s{1,3}比對\s,\s\s,\s\s\s,不比對\s\s\s\s |
? | 比對0或1次 | 5?比對5或0,不比對非5和0 |
+ | 比對一次或多次 | \S+比對一個以上\S,不比對非一個以上\S |
* | 比對0次以上 | \W*比對0以上\W,不比對非N*\W |
3) 字元定位文法:
重複文法 | 文法解釋 | 文法例子 |
^ | 定位後面模式開始位置 | |
$ | 前面模式位于字元串末端 | |
\A | 前面模式開始位置 | |
\z | 前面模式結束位置 | |
\Z | 前面模式結束位置(換行前) | |
\b | 比對一個單詞邊界 | |
\B | 比對一個非單詞邊界 |
4) 轉移比對文法:
轉義文法 | 涉及字元(文法解釋) | 文法例子 |
“\”+實際字元 | \ . * + ? | ( ) { }^ $ | 例如:\\比對字元“\” |
\n | 比對換行 | |
\r | 比對回車 | |
\t | 比對水準制表符 | |
\v | 比對垂直制表符 | |
\f | 比對換頁 | |
\nnn | 比對一個8進制ASCII | |
\xnn | 比對一個16進制ASCII | |
\unnnn | 比對4個16進制的Uniode |
下面我們結合例子來學習一下正規表達式的文法:
package learn.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** 正規表達式*/
public class RegexDemo {
/** 比對 */
public static boolean matchsString(String string, String regex) {
if (string != null && regex != null) {
return string.matches(regex);
} else {
return false;
}
}
/** 替換 */
public static String replaceString(String string, String regex,String newString) {
if (string != null && regex != null) {
return string.replaceAll(regex, newString);
} else {
return null;
}
}
/** 分割 */
public static String[] splitString(String string, String regex) {
if (string != null && regex != null) {
return string.split(regex);
} else {
return null;
}
}
/** 換行列印 */
public static void println(String string) {
System.out.println(string);
}
/** 不換行列印 */
public static void print(String string) {
System.out.print(string);
}
/** 測試 */
public static void main(String[] args) {
/********************************************************************************************/
/*
* 1.反斜杠(\\)字元串分割測試*/
println("1.反斜杠(\\)字元串分割測試");
String splitString1 = "C:\\Windows\\notepad.exe";
/*因為在Java的字元串中一個反斜杠的意義是"轉念字元", 是以要得到一個真正的反斜杠字元"\",
* 必須輸入一個兩個反斜杠(\\), 也就是要用第一個反斜杠轉義第二個反斜杠,而我們這裡寫的反斜杠又是要用于正規表達式中,
* 正規表達式中的一個反斜杠的意義同Java字元串一樣,是以這裡要輸入四個反斜杠
*/
String splitRegex1 = "\\\\";
String splitResult1[] = splitString(splitString1, splitRegex1);
println("\t被分割的的字元串:" + splitString1);
println("\t正規表達式:" + splitRegex1);
println("\t分割字元串的結果:");
for (int i = 0; i < splitResult1.length; i++) {
String s = splitResult1[i];
println("\t\t第" + (i + 1) + "個子串: " + s);
}
/********************************************************************************************/
/*
* 2.疊詞字元串分割測試
*/
println("2.疊詞字元串分割測試");
String splitString2 = "How arre yooou?iammmmm fine.";
/*
* 這個正規表達式使用了分組的概念,為了讓規則的結果被重用,則可以用一對小括号”()“将裡面的内容分為一個組,
* 并自動給這個組從左至右編号(從1開始),使用反斜杠加上組的編号(就是這裡的”\1“)引用這個組,
* 這裡的加号”+“代表前面的疊詞出現了一次或多次
*/
String splitRegex2 = "(.)\\1+";
String splitResult2[] = splitString(splitString2, splitRegex2);
println("\t被分割的的字元串:" + splitString2);
println("\t正規表達式:" + splitRegex2);
println("\t分割字元串的結果:");
for (int i = 0; i < splitResult2.length; i++) {
String s = splitResult2[i];
println("\t\t第" + (i + 1) + "個子串: " + s);
}
/********************************************************************************************/
/*
* 3.替換重複字母測試
*/
println("3.替換重複字母測試");
String replaceString1 = "????****abcdefffghijjjjkkklmnopqrstttuvvvvwxyz你你你你你你你你好好好";
/*
* 這裡我們将一串字母中的連續重複字母去重,replaceMent1中的美元符($)加上組的編号可以在替換時取到前面替換規則(replaceRegex1)中該編号對應組的值
*/
String replaceRegex1 = "(.)\\1+";
String replaceMent1="$1";
String replaceResult1 = replaceString(replaceString1, replaceRegex1,replaceMent1);
println("\t被替換前的字元串:" + replaceString1);
println("\t正規表達式:" + replaceRegex1);
println("\t被替換後的字元串:"+ replaceResult1);
/********************************************************************************************/
/*
* 4.電話号碼比對測試
*/
println("4.電話号碼比對測試");
String matchsString1 = "18888888888";
/*
* 比對電話号碼,第一位是1,第二位是(3、5、7、8)中的一位,後面還有9位任意數字
*/
String matchsRegex1 = "1[3|5|7|8]\\d{9}";
boolean matchsResult1 = matchsString(matchsString1,matchsRegex1);
println("\t比對測試的字元串:" + matchsString1);
println("\t正規表達式:" + matchsRegex1);
println("\t比對的結果:"+ matchsResult1);
/********************************************************************************************/
/*
* 5.子串擷取測試
*/
println("5.子串擷取測試");
String subString1 = "no.1abcno.2defno.3ghijk";
/*
* 這裡我們能取出以”no.“開頭,以數字結尾的子串,第一位是1,第二位是(3、5、7、8)中的一位,後面還有9位任意數字,使用Pattern類和Matcher類來擷取子串
*/
String subRegex1 = "no\\.\\d+";
Pattern pattern=Pattern.compile(subRegex1);
Matcher matcher=pattern.matcher(subString1);
println("\t擷取子串測試的字元串:" + subString1);
println("\t正規表達式:" + subRegex1);
println("\t符合規則的子串:");
for (int i=1;matcher.find();i++) {
String s = matcher.group();
println("\t\t第" + i + "個符合規則的子串: " + s+",在原字元中的位置是:"+matcher.start()+"-->"+matcher.end());
}
}
}
程式輸出:
1.反斜杠(\)字元串分割測試
被分割的的字元串:C:\Windows\notepad.exe
正規表達式:\\
分割字元串的結果:
第1個子串: C:
第2個子串: Windows
第3個子串: notepad.exe
2.疊詞字元串分割測試
被分割的的字元串:How arre yooou?iammmmm fine.
正規表達式:(.)\1+
分割字元串的結果:
第1個子串: How a
第2個子串: e y
第3個子串: u?i a
第4個子串: fine.
3.替換重複字母測試
被替換前的字元串:????****abcdefffghijjjjkkklmnopqrstttuvvvvwxyz你你你你你你你你好好好
正規表達式:(.)\1+
被替換後的字元串:?*abcdefghijklmnopqrstuvwxyz你好
4.電話号碼比對測試
比對測試的字元串:18888888888
正規表達式:1[3|5|7|8]\d{9}
比對的結果:true
5.子串擷取測試
擷取子串測試的字元串:no.1abcno.2defno.3ghijk
正規表達式:no\.\d+
符合規則的子串:
第1個符合規則的子串: no.1,在原字元中的位置是:0-->4
第2個符合規則的子串: no.2,在原字元中的位置是:7-->11
第3個符合規則的子串: no.3,在原字元中的位置是:14-->18
3. 常用的正規表達式
用途 | 表達式 |
驗證手機号碼 | 1[3|5|7|8|]\d{9} |
提取資訊中的網絡連結 | (h|H)(r|R)(e|E)(f|F) *=*('|")?(\w|\\|\/|\.)+('|"|*|>)? |
提取資訊中的郵件位址 | \w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* |
提取資訊中的圖檔連結 | (s|S)(r|R)(c|C)*=*('|")?(\w|\\|\/|\.)+('|"|*|>)? |
提取資訊中的IP位址 | (\d+)\.(\d+)\.(\d+)\.(\d+) |
提取資訊中的中國手機号碼 | (86)*0*13\d{9} |
提取資訊中的中國固定電話号碼 | (\(\d{3,4}\)|\d{3,4}-|\s)?\d{8} |
提取資訊中的中國電話号碼(包括移動和固定電話) | (\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14} |
提取資訊中的中國郵政編碼 | [1-9]{1}(\d+){5} |
提取資訊中的中國身份證号碼 | \d{18}|\d{15} |
提取資訊中的整數 | \d{18}|\d{15} |
提取資訊中的浮點數(即小數) | (-?\d*)\.?\d+ |
提取資訊中的任何數字 | (-?\d*)(\.\d+)? |
提取資訊中的中文字元串 | [\u4e00-\u9fa5]* |
提取資訊中的雙位元組字元串 (漢字) | [^\x00-\xff]* |
不記得的時候多查查文檔就好了