正则表达式高级用法之分组的使用教程,


目录
  • 分组的使用场景
  • 分组的使用方法
  • 捕获组
  • 分组的使用实例
    • javascript 获取分组内容
    • java 获取分组内容
  • 小结
    • 补充:正则表达式分组及常见的方法
      • 总结

        分组的使用场景

        在书写正则表达式时,通常情况下,我们有两种场景会使用到分组。

        一是:对一个子表达式进行重复;二是:想要获取到子表达式匹配到的内容。

        • 对子表达式进行重复

        如果需要重复单个字符,直接在字符后面加上限定符即可,例如 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
        	}
        }
        

        总结

        到此这篇关于正则表达式高级用法之分组使用的文章就介绍到这了,更多相关正则表达式分组内容请搜索PHP之友以前的文章或继续浏览下面的相关文章希望大家以后多多支持PHP之友!

        您可能感兴趣的文章:
        • 正则表达式、分组、子匹配(子模式)、非捕获子匹配(子模式)
        • 正则表达式分组实例详解
        • 利用正则表达式将字符串分组示例代码
        • 浅谈正则表达式中的分组和引用实现方法
        • 正则表达式分组与引用的使用

        相关内容