恭喜你,Get到一份 正則表達式 食用指南

  • 2020 年 3 月 30 日
  • 筆記

先贊後看,養成習慣

前言

正則表達式

正則表達式: 定義一個搜索模式的字元串。

正則表達式可以用於搜索、編輯和操作文本。

正則對文本的分析或修改過程為:首先正則表達式應用的是文本字元串(text/string),它會以定義的模式從左到右匹配文本,每個源字元只匹配一次。

Java中正則表達式的使用

字元串內置正則

在 Java 中有四個內置的運行正則表達式的方法,分別是 matches()、split())、replaceFirst()、replaceAll()。注意 replace() 方法不支援正則表達式。

當僅且當正則匹配整個字元串時返回 true

示例程式碼

 System.out.println("lby".matches("lby"));  	        System.out.println("----------");    	        String[] array = "l b y".split("\s");  	        for (String item : array) {  	            System.out.println(item);  	        }  	        System.out.println("----------");    	        System.out.println("l b y".replaceFirst("\s", "-"));  	        System.out.println("----------");    	        System.out.println("l b y".replaceAll("\s", "-"));  

運行結果

true  ----------  l  b  y  ----------  l-b y  ----------  l-b-y  

regex包

java.util.regex 包主要包括以下三個類:

  1. Pattern 類 pattern 對象是一個正則表達式的編譯表示。Pattern 類沒有公共構造方法。要創建一個 Pattern 對象,你必須首先調用其公共靜態編譯方法,它返回一個 Pattern 對象。該方法接受一個正則表達式作為它的第一個參數。
  2. Matcher 類 Matcher 對象是對輸入字元串進行解釋和匹配操作的引擎。與Pattern 類一樣,Matcher 也沒有公共構造方法。你需要調用 Pattern 對象的 matcher 方法來獲得一個 Matcher 對象。
  3. PatternSyntaxException PatternSyntaxException 是一個非強制異常類,它表示一個正則表達式模式中的語法錯誤。

Java 中regex 包使用正則表達式基本步驟

  1. 通過正則表達式創建模式對象 Pattern。
  2. 通過模式對象 Pattern,根據指定字元串創建匹配對象 Matcher。
  3. 通過匹配對象 Matcher,根據正則表達式操作字元串。

例如

  import java.util.regex.Matcher;  import java.util.regex.Pattern;    public class TestRegex {  	public static void main(String[] args) {  		//定義一個字元串  		String text = "Hello Regex!";  		//創建一個Pattern對象  可以認為根據正則表達式獲取一個對應的對象          Pattern pattern = Pattern.compile("\w+");          // Java 中忽略大小寫,有兩種寫法:          // Pattern pattern = Pattern.compile("\w+", Pattern.CASE_INSENSITIVE);          // Pattern pattern = Pattern.compile("(?i)\w+"); // 推薦寫法          Matcher matcher = pattern.matcher(text);          // 遍例所有匹配的序列          while (matcher.find()) {              System.out.print("Start index: " + matcher.start());              System.out.print(" End index: " + matcher.end() + " ");              System.out.println(matcher.group());          }    	}  }    

運行的結果為:

Start index: 0 End index: 5 Hello

Start index: 6 End index: 11 Regex、

以上程式碼看不懂沒有關係,提前感受一下正則的神奇,接下來我們學習一下正則表達式的的語法。

正則表達式的語法

常見匹配符號

匹配所有單個字元,除了換行符(Linux 中換行是 n,Windows 中換行是 rn)

元字元

元字元是一個預定義的字元。

匹配一個數字,是 [0-9] 的簡寫

限定符

限定符定義了一個元素可以發生的頻率。

正則表達式

描述

舉例

*

匹配 >=0 個,是 {0,} 的簡寫

X* 表示匹配零個或多個字母 X,.*表示匹配任何字元串

+

匹配 >=1 個,是 {1,} 的簡寫

X+ 表示匹配一個或多個字母 X

?

匹配 1 個或 0 個,是 {0,1} 的簡寫

X? 表示匹配 0 個或 1 個字母 X

{X}

只匹配 X 個字元

d{3} 表示匹配 3 個數字,.{10}表示匹配任何長度是 10 的字元串

{X,Y}

匹配 >=X 且 <=Y 個

d{1,4} 表示匹配至少 1 個最多 4 個數字

*?

如果 ? 是限定符 * 或 + 或 ? 或 {} 後面的第一個字元,那麼表示非貪婪模式(儘可能少的匹配字元),而不是默認的貪婪模式

分組和反向引用

小括弧 () 可以達到對正則表達式進行分組的效果。

模式分組後會在正則表達式中創建反向引用。反向引用會保存匹配模式分組的字元串片斷,這使得我們可以獲取並使用這個字元串片斷。

在以正則表達式替換字元串的語法中,是通過 $ 來引用分組的反向引用,$0 是匹配完整模式的字元串(注意在 JavaScript 中是用 $& 表示);$1 是第一個分組的反向引用;$2 是第二個分組的反向引用,以此類推。

示例:

package com.baizhi.test;    public class RegexTest {        public static void main(String[] args) {          // 去除單詞與 , 和 . 之間的空格          String Str = "Hello , World .";          String pattern = "(\w)(\s+)([.,])";          // $0 匹配 `(w)(s+)([.,])` 結果為 `o空格,` 和 `d空格.`          // $1 匹配 `(w)` 結果為 `o` 和 `d`          // $2 匹配 `(s+)` 結果為 `空格` 和 `空格`          // $3 匹配 `([.,])` 結果為 `,` 和 `.`          System.out.println(Str.replaceAll(pattern, "$1$3")); // Hello, World.      }  }  

上面的例子中,我們使用了 [.] 來匹配普通字元 . 而不需要使用 [\.]。因為正則對於 [] 中的 .,會自動處理為 [.],即普通字元 . 進行匹配。

否定先行斷言(Negative lookahead)

我們可以創建否定先行斷言模式的匹配,即某個字元串後面不包含另一個字元串的匹配模式。

否定先行斷言模式通過 (?!pattern) 定義。比如,我們匹配後面不是跟著 "b" 的 "a":

a(?!b)  

指定正則表達式的模式

可以在正則的開頭指定模式修飾符。

  • (?i) 使正則忽略大小寫。
  • (?s) 表示單行模式("single line mode")使正則的 . 匹配所有字元,包括換行符。
  • (?m) 表示多行模式("multi-line mode"),使正則的 ^ 和 $ 匹配字元串中每行的開始和結束。

Java 中的反斜杠

反斜杠 在 Java 中表示轉義字元,這意味著 在 Java 擁有預定義的含義。

這裡例舉兩個特別重要的用法:

  • 在匹配 . 或 { 或 [ 或 ( 或 ? 或 $ 或 ^ 或 * 這些特殊字元時,需要在前面加上 \,比如匹配 . 時,Java 中要寫為 \.,但對於正則表達式來說就是 .。
  • 在匹配 時,Java 中要寫為 \\,但對於正則表達式來說就是 \。

注意:Java 中的正則表達式字元串有兩層含義,首先 Java 字元串轉義出符合正則表達式語法的字元串,然後再由轉義後的正則表達式進行模式匹配。

正則表達式常見應用示例

中文的匹配

[u4e00-u9fa5]+ 代表匹配中文字。

public static void test3(){  		String str = "這裡有個新手易范的錯誤,就是正angongsi";          Pattern pattern = Pattern.compile("[\u4e00-\u9fa5]+");          Matcher matcher = pattern.matcher(str);          while (matcher.find()) {              System.out.println(matcher.group());          }  	}  

數字範圍的匹配

比如,匹配 1990 到 2017。

**注意:**這裡有個新手易范的錯誤,就是正則 [1990-2017],實際這個正則只匹配 0 或 1 或 2 或 7 或 9 中的任一個字元。

正則表達式匹配數字範圍時,首先要確定最大值與最小值,最後寫中間值。

正確的匹配方式:

public static void test4(){  		String str = "1990n2010n2017nsdfgadfggadfgdfgdfgafdgasfdgan1998";          // 這裡應用了 (?m) 的多行匹配模式,只為方便我們測試輸出          // "^1990$|^199[1-9]$|^20[0-1][0-6]$|^2017$" 為判斷 1990-2017 正確的正則表達式          Pattern pattern = Pattern.compile("(?m)^1990$|^199[1-9]$|^20[0-1][0-6]$|^2017$");          Matcher matcher = pattern.matcher(str);          while (matcher.find()) {              System.out.println(matcher.group());          }  	}  

img 標籤的匹配

比如,獲取圖片文件內容,這裡我們考慮了一些不規範的 img 標籤寫法:

public static void test5(){  		 String str = "<img  src='aaa.jpg' /><img src=bbb.png/><img src="ccc.png"/>" +  	                "<img src='ddd.exe'/><img src='eee.jpn'/>";  	        // 這裡我們考慮了一些不規範的 img 標籤寫法,比如:空格、引號  	        Pattern pattern = Pattern.compile("<img\s+src=(?:['"])?(?<src>\w+.(jpg|png))(?:['"])?\s*/>");  	        Matcher matcher = pattern.matcher(str);  	        while (matcher.find()) {  	            System.out.println(matcher.group("src"));  	        }  	}  

郵箱匹配

郵箱匹配的正則的寫法有很多,這裡給出一種參考的寫法。

合法E-mail地址:

  1. 必須包含一個並且只有一個符號「@」
  2. 第一個字元不得是「@」或者「.」
  3. 不允許出現「@.」或者.@
  4. 結尾不得是字元「@」或者「.」
  5. 允許「@」前的字元中出現「+」
  6. 不允許「+」在最前面,或者「+@」

等等

示例程式碼

public static void test6(){  		 String check = "^([a-z0-9A-Z]+[-|\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\.)+[a-zA-Z]{2,}$";  	     Pattern regex = Pattern.compile(check);  	     Matcher matcher = regex.matcher("[email protected]");  	     boolean isMatched = matcher.matches();  	     System.out.println(isMatched);  	}  

手機號匹配

	public static void test7(){  		String check = "^((13[0-9])|(15[^4])|(18[0-9])|(17[0-9])|(147))\d{8}$";  	     Pattern regex = Pattern.compile(check);  	     Matcher matcher = regex.matcher("18638693953");  	     boolean isMatched = matcher.matches();  	     System.out.println(isMatched);  	}  

url匹配

public static void test8(){  		String url = "http://www.lubingyang.com/";  		String regex = "(https?://(w{3}\.)?)?\w+\.\w+(\.[a-zA-Z]+)*(:\d{1,5})?(/\w*)*(\??(.+=.*)?(&.+=.*)?)?";  		boolean isMatched = Pattern.matches(regex, url);  		System.out.println(isMatched);  	}

Tags: