20-JavaSE基础巩固练习:捕获分组和非捕获分组

本文介绍了正则表达式中的分组概念,包括捕获分组和非捕获分组。通过实例展示了如何使用分组进行字符串匹配和替换,如判断字符串开始和结束部分是否一致,以及实现"口吃替换"。同时,解释了组号的规则以及非捕获分组在实际使用中的作用,如在身份证号码验证中的应用。
摘要由CSDN通过智能技术生成

分组

一、概述

  • 分组就是一个小括号

    在这里插入图片描述

  • 每组是有组号的,也就是序号。

  • 规则1:从1开始,连续不间断。

  • 规则2:以左括号为基准,最左边的是第一组,其次为第二组,以此类推!

    在这里插入图片描述



二、捕获分组的练习

1、练习一
  • 捕获分组就是把这一组的数据捕获出来,再用一次。
  • 需求1:判断一个字符串的开始字符和结束字符是否一致?只考虑一个字符
    • 举例a123ab456b17891&abc&
  • 需求2:判断一个字符串的开始部分和结束部分是否一致?可以有多个字符
    • 举例abc123abcb456b123789123&!@abc&!@
  • 需求3:判断一个字符串的开始部分和结束部分是否一致?开始部分内部每个字符也需要一致
    • 举例aaa123aaabbb456bbb111789111&&abc&&
package com.app.demo27_regex;

public class Test9 {
    public static void main(String[] args) {
        /*
            捕获分组的练习:
                捕获分组就是把这一组的数据捕获出来,再用一次。
                规则:以左括号为基准,最左边的是第一组,其次为第二组,以此类推!
         */
        // 需求1:判断一个字符串的开始字符和结束字符是否一致?只考虑一个字符
        // 举例:a123a、b456b、17891、&abc&
        /*
            (.): 表示把首字符分成一组,可以出现1个任意字符
            .+: 表示任意字符至少出现1次
            \\1: 表示把第1组的内容再用1次
         */
        String regex1 = "(.).+\\1";
        System.out.println("a123a".matches(regex1));
        System.out.println("b456b".matches(regex1));
        System.out.println("17891".matches(regex1));
        System.out.println("&abc&".matches(regex1));
        System.out.println("a123b".matches(regex1));
        System.out.println("----------------");

        // 需求2:判断一个字符串的开始部分和结束部分是否一致?可以有多个字符
        // 举例:abc123abc、b456b、123789123、&!@abc&!@
        /*
            (.+): 表示把首字符分成一组,首字符至少出现1次
            .+: 表示任意字符至少出现1次
            \\1: 表示把第1组的内容再用1次
         */
        String regex2 = "(.+).+\\1";
        System.out.println("abc123abc".matches(regex2));
        System.out.println("b456b".matches(regex2));
        System.out.println("123789123".matches(regex2));
        System.out.println("&!@abc&!@".matches(regex2));
        System.out.println("abc123abf".matches(regex2));
        System.out.println("----------------");

        // 需求3:判断一个字符串的开始部分和结束部分是否一致?开始部分内部每个字符也需要一致
        // 举例:aaa123aaa、bbb456bbb、111789111、&&abc&&
        /*
            规则细节:以左括号为基准,最左边的是第一组,其次为第二组,以此类推!
            (.): 表示把首字符分成一组
            \\2*: 表示把第2组的内容再用0次或多次
            .+: 表示任意字符至少出现1次
            \\1: 表示把第1组的内容再1次
            ((.)\\2*): 表示把第1组、把第2组内容再用0次或多次分成一组
         */
        String regex3 = "((.)\\2*).+\\1";
        System.out.println("aaa123aaa".matches(regex3));
        System.out.println("bbb456bbb".matches(regex3));
        System.out.println("111789111".matches(regex3));
        System.out.println("&&abc&&".matches(regex3));
        System.out.println("abc456abc".matches(regex3));
        System.out.println("----------------");
    }
}
true
true
true
true
false
----------------
true
true
true
true
false
----------------
true
true
true
true
false
----------------

Process finished with exit code 0



小结
  • 后续还要继续使用本组的数据。

  • 正则内部使用:

    \\组号
    
  • 正则外部使用:

    $组号
    


2、练习二:口吃替换
  • 需求:将字符串:“我要学学编编编编编程程程程程程程程”,替换为:“我要学编程”
package com.app.demo27_regex;

public class Test10 {
    public static void main(String[] args) {
        /*
            需求:
                将字符串:“我要学学编编编编编程程程程程程程程”
                替换为:“我要学编程”
         */
        String str = "我要学学编编编编编程程程程程程程程";
        /*
            (.) 表示把重复的内容看作一组
            \\1 表示把第1组的内容再用1次
            +   表示把第1组的内容再用至少1次,可以是多次
            $1  表示在正则表达式外部使用第1组的内容
         */
        String result = str.replaceAll("(.)\\1+", "$1");
        System.out.println(result);
    }
}
我要学编程

Process finished with exit code 0




三、非捕获分组

  • 分组之后不需要再用本组数据,仅仅把数据括起来。
符号含义举例
(? : 正则)获取所有Java(?:8|11|17)
(? = 正则)获取前面部分Java(?=8|11|17)
(? ! 正则)获取不是指定内容的前面部分Java(?!8|11|17)
package com.app.demo27_regex;

public class Test11 {
    public static void main(String[] args) {
        /*
            非捕获分组:
                分组之后不需要再用本组数据,仅仅把数据括起来。

            身份证号码:
               41080119930228457x
               510801197609022309
               15040119810705387X
               430102197606046442
         */
        // 身份证号的简易正则表达式
        String IDRegex = "[1-9]\\d{16}(\\d|X|x)";

        /*
            非捕获分组:仅仅是把数据括起来
            特点:不占用组号
            (?:) (?=) (?!)  这些都是非捕获分组,使用最多的是(?:)
         */
        // 这里\\1报错原因:(?:) 就是非捕获分组,此时是不占用组号的
        String IDRegex1 = "[1-9]\\d{16}(?:\\d|X|x)\\1";
        System.out.println("41080119930228457x".matches(IDRegex1));

        String ID = "15040119810705387X";
        /*
            运行时会报错:Exception in thread "main" java.lang.IndexOutOfBoundsException: No group 1
            意思就是说没有组号为1的正则
         */
        String result = ID.replaceAll("[1-9]\\d{16}(?:\\d|X|x)", "$1");
        System.out.println(result);
    }
}
false
Exception in thread "main" java.lang.IndexOutOfBoundsException: No group 1
	at java.util.regex.Matcher.start(Matcher.java:375)
	at java.util.regex.Matcher.appendReplacement(Matcher.java:880)
	at java.util.regex.Matcher.replaceAll(Matcher.java:955)
	at java.lang.String.replaceAll(String.java:2223)
	at com.app.demo27_regex.Test11.main(Test11.java:30)

Process finished with exit code 1




总结

1、正则表达式中分组有哪两种?

  • 捕获分组、非捕获分组

2、捕获分组(默认)是什么?

  • 可以获取每组中的内容反复使用

3、组号的特点是什么?

  • (1)从1开始,连续不间断
  • (2)以左括号为基准,最左边的是第一组,往后的为第二、三…组

4、非捕获分组是什么?

  • 分组之后不需要再用本组数据,仅仅把数据括起来,不占组号
  • (?: )、(?=)、(?!),这三个都是非捕获分组
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值