首頁 > 軟體

正規表示式高階用法之分組的使用教學

2022-09-20 22:02:38

分組的使用場景

在書寫正規表示式時,通常情況下,我們有兩種場景會使用到分組。

一是:對一個子表示式進行重複;二是:想要獲取到子表示式匹配到的內容。

  • 對子表示式進行重複

如果需要重複單個字元,直接在字元后面加上限定符即可,例如 a+ 表示匹配1個或一個以上的a,a?表示匹配0個或1個a。

但是我們如果要對多個字元進行重複的話,就需要用到 分組

比如:(ab){3} 表示 ab 字元重複3次

正則中常用的限定符如下:

表示式說明
X ?X ,一次或一次也沒有
X *X ,零次或多次
X +X ,一次或多次
X { n }X ,恰好 n 次
X { n ,}X ,至少 n 次
X { n , m }X ,至少 n 次,但是不超過 m 次
  • 獲取到子表示式匹配到的內容

比如表示式: [a-z]*d*[a-z]*,它表示a-z的字元重複0到多次,後面緊跟0到多個數位,後面再跟上多個a-z的字元。
顯然,字串 abcd324232efg 是滿足匹配的串。那麼,如果我們只想要獲取到匹配串中數位 324232 後面的串 efg 呢?

這時,就可以通過分組的方式來改寫正規表示式: [a-z]*d*([a-z]*)。這樣,我們就可以通過獲取第 1 個分組匹配到的內容來達到目的。

分組的使用方法

正則中通過小括號“()”來指定需要重複的子表示式,然後再加上限定符對這個子表示式進行重複。

例如:(abc)? 表示0個或1個abc 。

一組括號裡面的表示式就表示一個分組 。

捕獲組

分組可以分為兩種形式,捕獲組非捕獲組

捕獲組和非捕獲組的區別就是:捕獲組表示的分組會捕獲文字(即:匹配字元),而非捕獲組表示的分組不會捕獲文字。

捕獲組可以通過從左到右計算其開括號來編號

例如,在表示式 (A)(B(C)) 中,存在四個這樣的組:

分組編號分組編號對應的子表示式
0(A)(B(C))
1(A)
2(B(C))
3(C)

注意:第0個分組始終代表整個表示式

分組的序號可以通過 Back 參照(反向參照) 在表示式中使用,也可以在匹配操作完成後從匹配器檢索出分組匹配到的內容。
反向參照的知識將會在後續的文章中進行分析。

分組的使用範例

在一個完整的正則中,如果我們只想獲取到某個子表示式匹配到的內容,就可以通過分組來達到目的。

比如:

待匹配串:abcd324232efg

想要獲取到這個字串中第二次連續出現的字母子串efg

我們可以通過分組的方式書寫正則: [a-z]*d*([a-z]*)

可以看到,我們通過子表示式([a-z]*)來匹配第二次連續出現之母的子串,並且通過()新增了分組,這樣,我們就可以通過分組來獲取到相應的匹配內容了。

具體的獲取方法不同的語言的語法可能會有差異,但是原理是相通的。

下面就來看一下 javascript 和 java 中是如何進行處理的?

javascript 獲取分組內容

var str = "abcd324232efg";
var reg = new RegExp("([a-z]*)(\d*)([a-z]*)");
var arr = str.match(reg);
// 顯示匹配到的分組內容
alert(arr[0] + "===" + arr[1] + "===" + arr[2] + "===" + arr[3]);
alert(RegExp.$1 + "-----" + RegExp.$2 + "----" + RegExp.$3);  

上面的例子中,我新增了 3 個分組。

通過 arr[n]RegExp.$n 的方式都能獲取到分組匹配內容。

在 javascript 中 d 需要進行跳脫

java 獲取分組內容

public static void main(String[] args) {
    String str = "abcd324232efg";
    Pattern pattern = Pattern.compile("([a-z]*)(\d*)([a-z]*)");
    Matcher matcher = pattern.matcher(str);
    if (matcher.find()) {
        System.out.println(matcher.group());
        System.out.println(matcher.group(0));
        System.out.println(matcher.group(1));
        System.out.println(matcher.group(2));
        System.out.println(matcher.group(3));
    }
}

在 java 中,通過 Matcher.group(n) 的方式拿到分組匹配內容。

在 javascript 中 d 需要進行跳脫

小結

分組通常有兩種使用場景:一是:對一個子表示式進行重複;二是:想要獲取到子表示式匹配到的內容。

分組是通過 () 來表示的,它是通過從左到右計算其開括號來進行編號的。

補充:正規表示式分組及常見的方法

/*
 * 正規表示式分組功能:
 * 		捕獲組可以通過從左到右計算其開括號來編號。例如,在表示式 ((A)(B(C))) 中,存在四個這樣的組: 	
 * split(regex)  引數是正規表示式    返回值是一個陣列
 * replaceAll(regex,replacement)	第一個引數是正規表示式, 第二個引數要替換成的字串
 */
import java.util.Arrays;
public class RegexApply {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
//		demo1();
//		demo2();
//		demo3();
//		demo4();
//		demo5();
//		demo6();
	}
	private static void demo6() {
		/*
		 * \.  ""  將所有的. 替換為空字串
		 * (.)\1+	"$1"	將第一組出現的多次都替換 第一組出現的一次  $ 代表首字元
		 */
		String s = "我..我我...我....愛..愛愛愛....愛愛..學.學學..學學學...學習習..習...習.習.習......習習習習";
		String s2 = s.replaceAll("\.+", "");
		String s3 = s2.replaceAll("(.)\1+", "$1");	
		System.out.println(s3);
	}
	private static void demo5() {
		/*
		 * 疊詞切割: "acyyfgttthjzzzzzko";
		 * (.)\1+	//1+代表第一組出現一次到多次
		 */
		String s = "acyyfgttthjzzzzzko";
		String regex = "(.)\1+";					//1+代表第一組出現一次到多次
		String[] arr = s.split(regex);
		
		for (int i = 0; i < arr.length; i++) {
			System.out.println(arr[i]);
		}
	}
	private static void demo4() {
		/*
		 * 疊詞 捕獲組 (.)\1(.)\2     \1代表第一組又出現一次	\2代表第二組又出現一次
		 * (..)\1					  \1代表第一組又出現了一次
		 */
		//疊詞  飄飄亮亮,美美麗麗
		String regex2 = "(.)\1(.)\2";					//\1代表第一組又出現一次	\2代表第二組又出現一次
		System.out.println("漂漂亮亮".matches(regex2));	//true
		System.out.println("美美麗麗".matches(regex2));	//false
		System.out.println("高高興興".matches(regex2));	//true
		System.out.println("死啦死啦".matches(regex2));	//false
		System.out.println("----------------------");
		//疊詞 漂亮漂亮,美麗美麗
		String regex = "(..)\1";
		System.out.println("死啦死啦".matches(regex));		//true			
		System.out.println("高興高興".matches(regex));		//true
		System.out.println("快快樂樂".matches(regex));		//false
	}
	private static void demo3() {
		/*
		 * replaceAll(regex,replacement)	第一個引數是正規表示式, 第二個引數要替換成的字串
		 */
		String s = "aaoo1ddd3jgjao";
		String regex = "\d";
		String s2 = s.replaceFirst(regex, "");
		String s3 = s.replaceAll(regex, "");
		System.out.println(s2);					//aaooddd3jgjao
		System.out.println(s3);					//aaoodddjgjao
	}
	private static void demo2() {
		/*
		 * split(regex)  引數是正規表示式    返回值是一個陣列 
		 */
		String s = "星期一.星期二.星期三.星期四";
		String[] array = s.split("\.");
		System.out.println(Arrays.toString(array));
	}
	private static void demo1() {
		/*
		 * 校驗電話號碼
		 * 1.必須是5-15位數位
		 * 2.開頭不能位0
		 * 3.必須是純數位
		 */
		String regex = "[1-9]\d{5,15}";
		System.out.println("804360385".matches(regex));				//true
		System.out.println("430763075439703307503".matches(regex));	//false
		System.out.println("03534534".matches(regex));				//false
	}
}

總結

到此這篇關於正規表示式高階用法之分組使用的文章就介紹到這了,更多相關正規表示式分組內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com