Java基础:正则表达式
相關閱讀
1. 正則表達式概述
正則表達式,又稱正規表示法、常規表示法(英語:Regular Expression,在代碼中常簡寫為regex、regexp或RE),計算機科學的一個概念。正則表達式使用單個字符串來描述、匹配一系列符合某個句法規則的字符串。在很多文本編輯器里,正則表達式通常被用來檢索、替換那些符合某個模式的文本
許多程序設計語言都支持利用正則表達式進行字符串操作。例如,在Perl中就內建了一個功能強大的正則表達式引擎。正則表達式這個概念最初是由Unix中的工具軟件(例如sed和grep)普及開的。正則表達式通常縮寫成“regex”,單數有regexp、regex,復數有regexps、regexes、regexen
正則表達式是對字符串操作的一種邏輯公式,就是用事先定義好的一些特定字符、及這些特定字符的組合,組成一個“規則字符串”,這個“規則字符串”用來表達對字符串的一種過濾邏輯
1.1 給定一個正則表達式和另一個字符串,我們可以達到如下的目的
- 給定的字符串是否符合正則表達式的過濾邏輯(稱作“匹配”)
- 可以通過正則表達式,從字符串中獲取我們想要的特定部分
1.2 正則表達式的特點
- 靈活性、邏輯性和功能性非常的強;
- 可以迅速地用極簡單的方式達到字符串的復雜控制。
- 對于剛接觸的人來說,比較晦澀難懂。
由于正則表達式主要應用對象是文本,因此它在各種文本編輯器場合都有應用,小到著名編輯器EditPlus,大到Microsoft Word、Visual Studio等大型編輯器,都可以使用正則表達式來處理文本內容
2. 正則表達式基礎知識
2.1 規則字符在java.util.regex Pattern類中
2.2 常見符號
2.2.1 字符
| X | 字符X |
| \\ | 反斜線 |
| \t | 制表符 (‘\u0009’) |
| \n | 回車 |
| \r | 換行 |
| \f | 換頁符 (‘\u000C’) |
| \a | 報警 (bell) 符 (‘\u0007’) |
2.2.2 字符類
| [abc] | a、b或c |
| [^abc] | 任何字符,除了a、b或c |
| [a-zA-Z] | a到z,或A到Z |
| [0-9] | 0到9的字符 |
| [a-d[m-p]] | a到 d或 m 到 p:[a-dm-p](并集) |
| [a-z&&[def]] | d、e或 f(交集) |
| [a-z&&[^bc]] | a到 z,除了 b和 c:[ad-z](減去) |
| [a-z&&[^m-p]] | a到 z,而非 m到 p:[a-lq-z](減去) |
2.2.3 預定義字符
| . | 任何字符 |
| \d | 數字:[0-9] |
| \D | 非數字: [^0-9] |
| \s | 空白字符:[ \t\n\x0B\f\r] |
| \S | 非空白字符:[^\s] |
| \w | 單詞字符:[a-zA-Z_0-9] |
| \W | 非單詞字符:[^\w] |
2.3 邊界匹配器
| ^ | 行開頭 |
| $ | 行結尾 |
| \b | 單詞邊界 |
| \B | 非單詞邊界 |
| \A | 輸入的開頭 |
| \G | 上一個匹配的結尾 |
| \Z | 輸入的結尾,僅用于最后的結束符(如果有的話) |
| \z | 輸入的結尾 |
2.3.1 Greedy數量詞
| X? | 0次或1次 |
| X* | 0次以上 |
| X+ | 1次以上 |
| X{n} | 恰好n次 |
| X{n,} | 至少n次 |
| X{n,m} | n-m次 |
2.3.2 組和捕獲
分組可以分為兩種形式,捕獲組和非捕獲組。
捕獲組可以通過從左到右計算其開括號來編號。例如,在表達式 ((A)(B(C)))中,存在四個這樣的組:
- 分組0:((A)(B(C)))
- 分組1:(A)
- 分組2:(B(C))
- 分組3:(C)
正則表達式中每個”()”內的部分算作一個捕獲組,每個捕獲組都有一個編號,從1,2…,編號0代表整個匹配到的內容,組零始終代表整個表達式。
之所以這樣命名捕獲組是因為在匹配中,保存了與這些組匹配的輸入序列的每個子序列。捕獲的子序列稍后可以通過 Back 引用(反向引用) 在表達式中使用,也可以在匹配操作完成后從匹配器檢索。
Back引用(\n)是說在后面的表達式中我們可以使用組的編號來引用前面的表達式所捕獲到的文本序列。注意:反向引用,引用的是前面捕獲組中的文本而不是正則,也就是說反向引用處匹配的文本應和前面捕獲組中的文本相同,這一點很重要。
例如 ([” ‘]).*\1 其中使用了分組,\1就是對引號這個分組的引用,它匹配包含在兩個引號或者兩個單引號中的所有字符串,如,”abc” 或 “’ ” 或’ ” ’ ,但是請注意,它并不會對”a’或者 ‘a”匹配。原因上面已經說明,Back引用只是引用文本而不是表達式。
捕獲組的作用就是為了可以在正則表達式內部或者外部(Java方法)引用它。在另一個字符串引用捕獲組的內容的方法(“"),在替換中常用匹配組的內容。$n用來匹配第n個()里的內容。
利用Matcher中的group(int group)獲取捕獲組內容。
- 捕獲組命名
如果捕獲組的數量非常多,那都用數字進行編號并引用將會非?;靵y,并且難以記憶每個捕獲組的內容及意義,因此對捕獲組命名顯得尤為重要;Java 7開始提供了對捕獲組命名的語法,并且可以通過捕獲組的名稱對捕獲組反向引用(內外都行)。
命名捕獲組的語法格式:(?<自定義名>expr),例如:(?\d{4})-(?\d{2}-(?\d{2}))
有三個命名捕獲組year、date和day,從左到右編號分別為1、2、3(編號同樣是有效的)
- 非捕獲組
非捕獲組,只需要將捕獲組中”()”變為”(?:)”即可。
以 (?) 開頭的組是純的非捕獲組,它不捕獲文本 ,也不針對組合計進行計數。就是說,如果小括號中以?號開頭,那么這個分組就不會捕獲文本,當然也不會有組的編號,因此也不存在Back引用。
我們通過捕獲組就能夠得到我們想要匹配的內容了,那為什么還要有非捕獲組呢?原因是捕獲組捕獲的內容是被存儲在內存中,可供以后使用,比如反向引用就是引用的內存中存儲的捕獲組中捕獲的內容。而非捕獲組則不會捕獲文本,也不會將它匹配到的內容單獨分組來放到內存中。所以,使用非捕獲組較使用捕獲組更節省內存。在實際情況中我們要酌情選用。
3. 正則表達式的應用
3.1 判斷功能
public boolean matches(String regex):編譯給定正則表達式并嘗試將給定輸入與其匹配。3.2 分割功能
public String[] split(String regex):根據指定的正則表達式分割字符串3.3 替換功能
public String replaceAll(String regex,String replacement)使用給定的 replacement 替換此字符串所有匹配給定的正則表達式的子字符串。
3.4 獲取功能
Pattern和Matcher類的使用
package cn.itcast_05; import java.util.regex.Matcher; import java.util.regex.Pattern; /** 獲取功能* Pattern和Matcher類的使用* * 模式和匹配器的基本使用順序*/ public class RegexDemo {public static void main(String[] args) {// 模式和匹配器的典型調用順序// 把正則表達式編譯成模式對象Pattern p = Pattern.compile("a*b");// 通過模式對象得到匹配器對象,這個時候需要的是被匹配的字符串Matcher m = p.matcher("aaaaab");// 調用匹配器對象的功能boolean b = m.matches();System.out.println(b);//這個是判斷功能,但是如果做判斷,這樣做就有點麻煩了,我們直接用字符串的方法做String s = "aaaaab";String regex = "a*b";boolean bb = s.matches(regex);System.out.println(bb);} }Pattern 匹配模式
| compile() | 把正則表達式編譯成匹配模式 |
| matcher() | 根據匹配模式去匹配指定的字符串,得到匹配器 |
Matcher 匹配器
| matches() | 匹配字符串 |
| find() | 查找有沒有滿足條件的子串 |
| group() | 獲取滿足條件的子串 |
3.4 注意事項
Pattern類為正則表達式的編譯表示形式。指定為字符串的正則表達式必須首先被編譯為此類的實例。然后,可將得到的模式用于創建Matcher對象,依照正則表達式,該對象可以與任意字符序列匹配。執行匹配所涉及的所有狀態都駐留在匹配器中,所以多個匹配器可以共享同一模式
4. 正則表達式的練習
4.1 判斷功能:校驗郵箱
package cn.itcast_02; import java.util.Scanner; /** 校驗郵箱* * 分析:* A:鍵盤錄入郵箱* B:定義郵箱的規則* 1517806580@qq.com* liuyi@163.com* linqingxia@126.com* fengqingyang@sina.com.cn* fqy@itcast.cn* C:調用功能,判斷即可* D:輸出結果*/ public class RegexTest {public static void main(String[] args) {//鍵盤錄入郵箱Scanner sc = new Scanner(System.in);System.out.println("請輸入郵箱:");String email = sc.nextLine();//定義郵箱的規則//String regex = "[a-zA-Z_0-9]+@[a-zA-Z_0-9]{2,6}(\\.[a-zA-Z_0-9]{2,3})+";String regex = "\\w+@\\w{2,6}(\\.\\w{2,3})+";//調用功能,判斷即可boolean flag = email.matches(regex);//輸出結果System.out.println("flag:"+flag);} }4.2 分割功能
代碼示例:我有如下一個字符串:”91 27 46 3850”,請寫代碼實現最終輸出結果是:”27 3846 50 91”
package cn.itcast_03; import java.util.Arrays; /** 我有如下一個字符串:"91 27 46 38 50"* 請寫代碼實現最終輸出結果是:"27 38 46 50 91"* * 分析:* A:定義一個字符串* B:把字符串進行分割,得到一個字符串數組* C:把字符串數組變換成int數組* D:對int數組排序* E:把排序后的int數組在組裝成一個字符串* F:輸出字符串*/ public class RegexTest {public static void main(String[] args) {// 定義一個字符串String s = "91 27 46 38 50";// 把字符串進行分割,得到一個字符串數組String[] strArray = s.split(" ");// 把字符串數組變換成int數組int[] arr = new int[strArray.length];for (int x = 0; x < arr.length; x++) {arr[x] = Integer.parseInt(strArray[x]);}// 對int數組排序Arrays.sort(arr);// 把排序后的int數組在組裝成一個字符串StringBuilder sb = new StringBuilder();for (int x = 0; x < arr.length; x++) {sb.append(arr[x]).append(" ");}//轉化為字符串String result = sb.toString().trim();//輸出字符串System.out.println("result:"+result);} }4.3 替換功能:論壇中不能出現數字字符,用*替換
package cn.itcast_04; /** 替換功能* String類的public String replaceAll(String regex,String replacement)* 使用給定的 replacement 替換此字符串所有匹配給定的正則表達式的子字符串。 */ public class RegexDemo {public static void main(String[] args) {// 定義一個字符串String s = "helloqq12345worldkh622112345678java";// 我要去除所有的數字,用*給替換掉// String regex = "\\d+";// String regex = "\\d";//String ss = "*";// 直接把數字干掉String regex = "\\d+";String ss = "";String result = s.replaceAll(regex, ss);System.out.println(result);} }4.4 獲取功能:獲取由三個字符組成的單詞
package cn.itcast_05; import java.util.regex.Matcher; import java.util.regex.Pattern; /** 獲取功能:* 獲取下面這個字符串中由三個字符組成的單詞* da jia ting wo shuo,jin tian yao xia yu,bu shang wan zi xi,gao xing bu?*/ public class RegexDemo2 {public static void main(String[] args) {// 定義字符串String s = "da jia ting wo shuo,jin tian yao xia yu,bu shang wan zi xi,gao xing bu?";// 規則String regex = "\\b\\w{3}\\b";// 把規則編譯成模式對象Pattern p = Pattern.compile(regex);// 通過模式對象得到匹配器對象Matcher m = p.matcher(s);// 調用匹配器對象的功能// 通過find方法就是查找有沒有滿足條件的子串// public boolean find()// boolean flag = m.find();// System.out.println(flag);// // 如何得到值呢?// // public String group()// String ss = m.group();// System.out.println(ss);//// // 再來一次// flag = m.find();// System.out.println(flag);// ss = m.group();// System.out.println(ss);while (m.find()) {System.out.println(m.group());}// 注意:一定要先find(),然后才能group()// IllegalStateException: No match found// String ss = m.group();// System.out.println(ss);} }5. 正則表達式工具類
import java.util.regex.Matcher; import java.util.regex.Pattern;/*** 正則工具類 提供驗證郵箱、手機號、電話號碼、身份證號碼、數字等方法*/ public final class RegexUtils {/*** 驗證Email* * @param email* email地址,格式:zhangsan@sina.com,zhangsan@xxx.com.cn,xxx代表郵件服務商* @return 驗證成功返回true,驗證失敗返回false ^ :匹配輸入的開始位置。 \:將下一個字符標記為特殊字符或字面值。* :匹配前一個字符零次或幾次。 + :匹配前一個字符一次或多次。 (pattern) 與模式匹配并記住匹配。 x|y:匹配 x 或* y。 [a-z] :表示某個范圍內的字符。與指定區間內的任何字符匹配。 \w :與任何單詞字符匹配,包括下劃線。* * {n,m} 最少匹配 n 次且最多匹配 m 次 $ :匹配輸入的結尾。*/public static boolean checkEmail(String email) {String regex = "^(\\w)+(\\.\\w+)*@(\\w)+((\\.\\w{2,3}){1,3})$";return Pattern.matches(regex, email);}/*** 驗證身份證號碼* * @param idCard* 居民身份證號碼15位或18位,最后一位可能是數字或字母* @return 驗證成功返回true,驗證失敗返回false*/public static boolean checkIdCard(String idCard) {String regex = "[1-9]\\d{13,16}[a-zA-Z0-9]{1}";return Pattern.matches(regex, idCard);}/*** 驗證手機號碼(支持國際格式,+86135xxxx...(中國內地),+00852137xxxx...(中國香港))* * @param mobile* 移動、聯通、電信運營商的號碼段* <p>* 移動的號段:134(0-8)、135、136、137、138、139、147(預計用于TD上網卡)* 、150、151、152、157(TD專用)、158、159、187(未啟用)、188(TD專用)* </p>* <p>* 聯通的號段:130、131、132、155、156(世界風專用)、185(未啟用)、186(3g)* </p>* <p>* 電信的號段:133、153、180(未啟用)、189* </p>* <p>* 虛擬運營商的號段:170* </p>* @return 驗證成功返回true,驗證失敗返回false*/public static boolean checkMobile(String mobile) {String regex = "(\\+\\d+)?1[34578]\\d{9}$";return Pattern.matches(regex, mobile);}/*** 驗證固定電話號碼* * @param phone* 電話號碼,格式:國家(地區)電話代碼 + 區號(城市代碼) + 電話號碼,如:+8602085588447* <p>* <b>國家(地區) 代碼 :</b>標識電話號碼的國家(地區)的標準國家(地區)代碼。它包含從 0 到 9* 的一位或多位數字, 數字之后是空格分隔的國家(地區)代碼。* </p>* <p>* <b>區號(城市代碼):</b>這可能包含一個或多個從 0 到 9 的數字,地區或城市代碼放在圓括號——* 對不使用地區或城市代碼的國家(地區),則省略該組件。* </p>* <p>* <b>電話號碼:</b>這包含從 0 到 9 的一個或多個數字* </p>* @return 驗證成功返回true,驗證失敗返回false*/public static boolean checkPhone(String phone) {// String regex = "(\\+\\d+)?(\\d{3,4}\\-?)?\\d{7,8}$";String regex = "^1\\d{10}$";return Pattern.matches(regex, phone);}/*** 驗證整數(正整數和負整數)* * @param digit* 一位或多位0-9之間的整數* @return 驗證成功返回true,驗證失敗返回false*/public static boolean checkDigit(String digit) {String regex = "\\-?[1-9]\\d+";return Pattern.matches(regex, digit);}/*** 驗證整數和浮點數(正負整數和正負浮點數)* * @param decimals* 一位或多位0-9之間的浮點數,如:1.23,233.30* @return 驗證成功返回true,驗證失敗返回false*/public static boolean checkDecimals(String decimals) {String regex = "\\-?[1-9]\\d+(\\.\\d+)?";return Pattern.matches(regex, decimals);}/*** 驗證空白字符* * @param blankSpace* 空白字符,包括:空格、\t、\n、\r、\f、\x0B* @return 驗證成功返回true,驗證失敗返回false*/public static boolean checkBlankSpace(String blankSpace) {String regex = "\\s+";return Pattern.matches(regex, blankSpace);}/*** 驗證中文* * @param chinese* 中文字符* @return 驗證成功返回true,驗證失敗返回false*/public static boolean checkChinese(String chinese) {String regex = "^[\u4E00-\u9FA5]+$";return Pattern.matches(regex, chinese);}/*** 驗證日期(年月日)* * @param birthday* 日期,格式:1992-09-03,或1992.09.03* @return 驗證成功返回true,驗證失敗返回false*/public static boolean checkBirthday(String birthday) {String regex = "[1-9]{4}([-./])\\d{1,2}\\1\\d{1,2}";return Pattern.matches(regex, birthday);}/*** 驗證URL地址* * @param url* 格式:http://blog.csdn.net:80/xyang81/article/details/7705960? 或* http://www.csdn.net:80* @return 驗證成功返回true,驗證失敗返回false*/public static boolean checkURL(String url) {String regex = "(https?://(w{3}\\.)?)?\\w+\\.\\w+(\\.[a-zA-Z]+)*(:\\d{1,5})?(/\\w*)*(\\??(.+=.*)?(&.+=.*)?)?";return Pattern.matches(regex, url);}/*** 匹配中國郵政編碼* * @param postcode* 郵政編碼* @return 驗證成功返回true,驗證失敗返回false*/public static boolean checkPostcode(String postcode) {String regex = "[1-9]\\d{5}";return Pattern.matches(regex, postcode);}/*** 匹配IP地址(簡單匹配,格式,如:192.168.1.1,127.0.0.1,沒有匹配IP段的大小)* * @param ipAddress* IPv4標準地址* @return 驗證成功返回true,驗證失敗返回false*/public static boolean checkIpAddress(String ipAddress) {String regex = "[1-9](\\d{1,2})?\\.(0|([1-9](\\d{1,2})?))\\.(0|([1-9](\\d{1,2})?))\\.(0|([1-9](\\d{1,2})?))";return Pattern.matches(regex, ipAddress);}public static boolean checkNickname(String nickname) {String regex = "^[a-zA-Z0-9\u4E00-\u9FA5_]+$";return Pattern.matches(regex, nickname);}public static boolean hasCrossSciptRiskInAddress(String str) {String regx = "[`~!@#$%^&*+=|{}':;',\\[\\].<>~!@#¥%……&*——+|{}【】‘;:”“’。,、?-]";if (str != null) {str = str.trim();Pattern p = Pattern.compile(regx, Pattern.CASE_INSENSITIVE);Matcher m = p.matcher(str);return m.find();}return false;} }總結
以上是生活随笔為你收集整理的Java基础:正则表达式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java字符串格式化
- 下一篇: Android Manager