Java基础正则表达式简介

简单笔记

学习地址:https://www.bilibili.com/video/BV1Eq4y1E79W?spm_id_from=333.337.search-card.all.click&vd_source=8e584207f66e06e3a34787420e396cc8

快速入门和简介

快速入门

package com.scy;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class pattern {
    public static void main(String[] args) {
        String content = "Java是世界上使用最广泛的编程语言之一。Java最初由Sun Microsystems在1990年代开发," +
                    "用于开发从Web应用程序到移动应用程序到批处理应用程序的所有内容。Java最初是一种纯粹的面向对象的语言," +
                "但现在已经发展成为一种多范例语言,可以高度适应任何情况。" +
                "拥有庞大的开发人员社区和支持库,Java是开发几乎所有类型的应用程序的理想选择。";

        //提取文章中的所有英文单词
        //1.传统方法:遍历
        //2.正则表达式匹配

        //1.先创建一个Pattren对象,模式对象,可以理解为一个正则表达式对象
        Pattern pattern = Pattern.compile("[a-zA-z]+");
        //2.创建一个匹配器对象
        //理解:就是matcher匹配器按照pattern(模式/样式)到content文本中区匹配
        //找到返回true,否则返回false
        Matcher matcher = pattern.matcher(content);
        //3.可以开始循环匹配
        while (matcher.find()){
            //匹配内容,文本,放到m.group(0)
            System.out.println(matcher.group(0));
        }
    }
}

 正则表达式底层

 @Test
    public void test01(){
        String str = "1998年12月8日,第二代Java平台的企业版32EE发布。1999年6月,Sun公司发布了"+
                "第二代Java平台(简称为Java2)的3个版本:J2NE (Java2 Nicro Edition,Java2平台的微型版),应用于移动、无线及有限资源的环境;J2SE (Java 2 Standard Edition,Java 2平台的”+标准版)," +
                "应用于桌面环境;J2EE (Java 2Enterprise Edition,Java 2平台的企业版)," +
                "应+用3443于基于Java的应用服务器。Java 2平台的发布,是Java发展过程中最重要的一个"+
                "里程碑,标志着Java的应用开始普及9889;";

        //目标:匹配所有四个数字

        //1.\\d 表示任意一个数字
        String regStr = "\\d\\d\\d\\d";

        //2.创建模式对象 = 正则表达式对象
        Pattern pattren = Pattern.compile(regStr);

        //3.创建匹配器
        //说明:创建匹配器matcher,按照正则表达式的规则,去匹配content字符串
        Matcher matcher = pattren.matcher(str);

        //4.开始匹配
        while(matcher.find()){
            System.out.println(matcher.group(0));
        }
    }
   /*
    * 1.根据指定的规则,定位满足规则的子字符串(比如1999)
    * 2.找到后,将子字符串的开始的索引记录到 matcher对象的属性 int[] groups;*groups[0] = 31     把该子字符串的结束的索引+1的值记录到groups[1] = 35
    * 3.同时记录oldLast的值为子字符串的结束的索引+1的信即35,即下次执行find时,就从35开始匹配
    
    
    *  matcher.group(0)分析
    *   public String group(int group) {
    *    if (first < 0)
    *        throw new IllegalStateException("No match found");
    *    if (group < 0 || group > groupCount())
    *        throw new IndexOutOfBoundsException("No group " + group);
    *    if ((groups[group*2] == -1) || (groups[group*2+1] == -1))
    *        return null;
    *    return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
    *    }
    *    1.根据 groups[0]=轮和groups[1]=4 的记录的位置,从content开始截取子字符串返回
    *    就是[0,4)包含0但是不包含索引为4的位置
    */

 group()里面的参数

    while(matcher.find()){
            //1.如果正则表达式有(〕即分组
            //2.取出匹配的字符串规则如下
            //3. group(0)表示匹配到的子字符串
            //4. group(1)表示匹配到的子字符串的第一组字串
            //5. group(2)表示匹配到的子字符串的第2组字串
            //6. ...但是分组的数不能越界。
            System.out.println(matcher.group(0));
            System.out.println(matcher.group(1));
            System.out.println(matcher.group(2));
        }
   

分组(\d\d)(\d\d)

什么是分组,比如(\d\d)(\d\d),正则表达式中有(〕表示分组,第1个()表示第1组,第2个()表示第2组...*
1.根据指定的规则,定位满足规则的子字符串(比如(19)(98))
2.找到后,将子字符串的开始的索引记录到 matcher对象的属性int[] groups;* 
    2.1 groups[0] = 0,把该子字符串的结束的索引+1的值记录到 groups[1] = 4    
    2.2记录1组()匹配到的字符串groups[2] = 0 groups[3] = 2
    2.3记录2组()匹配到的字符串 groups[4] = 2 groups[5] = 3

正则语法

元字符-转义号 \\

符号说明:在我们使用正则表达式去检索某些特殊字符的时候,需要用到转义符号,否则检索不到结果,甚至会报错的。

案例:用$去匹配“abc$(”会怎样)

需要用到转义符号的字符有以下 . * + ( ) $ / \ ? [ ]  ^ {}

元字符-字符匹配符

Java的字符匹配符默认区分大小写,改变方式:

1.通过(?i)改为不区分大小写。例如(?i)abc可以匹配abc或ABC,a(?i)bc可以匹配bc或BC,a(?)b)c可以匹配b或B

2.通过设置参数不区分大小写。例如Pattern.compile(regStr, Pattern.CASE_INSENSITIVE); 

   @Test
    public void test02(){
        String context = "a1123";
        String regStr = "[a-z]";
        //String regStr = "abc"; //匹配abc,不忽略大小写
        //String regStr = "(?i)abc"; //匹配abc,全忽略大小写
        //String regStr = "a(?i)bc"; //匹配abc,bc忽略大小写
        //String regStr = "a((?i)b)c";
        //String regStr = "[A-Z]";
        //String regStr = "[^a-z]{2}";//连续两个不在a-z之间的数
        //String regStr = "[abc]{2}";//连续两个不在abc之间的
        //String regStr = "\\D";//不在0-9之间
        //String regStr = "\\w";//匹配任意英文字符,数字和下划线,相当于[a-zA-z0-9_]
        //String regStr = "\\s";//匹配空白字符
        //String regStr = "..";//匹配除\n以外的所有字符,如果匹配.本身就用\\.
        Pattern pattern = Pattern.compile(regStr);
        //Pattern pattern = Pattern.compile(regStr,Pattern.CASE_INSENSITIVE); //忽略所有大小写
        Matcher matcher = pattern.matcher(context);
        while(matcher.find()){
            System.out.println(matcher.group(0));
        }
    }

元字符-选择匹配符

public void test03(){
        String context = "shao邵少天xiadiyi";
        String regStr = "shao|邵|少";
        //String regStr = "[A-Z]";
        Pattern pattern = Pattern.compile(regStr,Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(context);
        while(matcher.find()){
            System.out.println(matcher.group(0));
        }
    }

元字符-限定符

java匹配默认是贪婪匹配,即尽可能的匹配多的部分,比如:a{3,4} aaaaaa12

会匹配出aaaa,而不是aaa和aaa

a+,1/多个a

a*,0/多个a

a1?,a1/a

 元字符-定位符号

全字符串匹配!

@Test
    public void test04(){
        String context = "123abc";//可以匹配到
        String content = "huanshunping spinghan";
        //String context1 = "a123abc";//匹配不到,因为不以数字开头
        String regStr = "^[0-9]+[a-z]*";
        //表示匹配边界的han这里的边界是指:被匹配的字符串最后,
        //也可以是空格的子字符串的后面
        //String regStr = "han\\b";
        Pattern pattern = Pattern.compile(regStr,Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(context);
        while(matcher.find()){
            System.out.println(matcher.group(0));
        }
    }

分组 

基本分组

(pattern) :非命名捕获,捕获匹配的子字符串,编号为 0 的第一个捕获是由整个正则表达式模式匹配的文本,其它捕获结果则根据左括号的顺寻从 1 开始自动编号
(?pattren)命名捕获,将匹配的子字符串捕获到一个组名称或编号名称中,用于name的字符串不能包含任何标点符号,并且不能以数字开头,可以使用单引号替代尖括号,例如 (?'name’)

String str = "(?<g1>\\d\\d)(?<g2>\\d\\d)";
sout(matcher.group(1));
sout(matcher.group("g1"));
//命名之后就会两种获取分组后子字符串的方法,没有命名只能通过顺序来获取

 非捕获分组

这种分组,后面就只能通过matcher.group(0)方式来获取到值,不能通过matcher.group(1),matcher.group(2)…等等,因为不是捕获分组

public class RegExp01 {
    public static void main(String[] args) {
        String content = "hello韩顺平教育 jack韩顺平老师 韩顺平同学hello";
        //String regStr = "韩顺平教育|韩顺平老师|韩顺平同学"
        //String regStr = "韩顺平(?:教育|老师|同学)";

        //只匹配韩顺平后面是  教育或者老师 的 韩顺平 的字符串
        //String regStr = "韩顺平(?=教育|老师)";

        //不匹配韩顺平后面是  教育或者老师 的 韩顺平 的字符串
        String regStr = "韩顺平(?!教育|老师)";
        
        Pattern pattern = Pattern.compile(regStr);
        Matcher matcher = pattern.matcher(content);
        while(matcher.find()){
            System.out.println(matcher.group(0));
        }
    }
}

 在 限定符(* + ? {n} {n,} {n,m}) 后面加上一个问号(?)表示非贪婪匹配

应用

1.汉字
2.邮政编码:要求:是1-9开头的一个六位数,比如:123890
3.QQ号码:要求:是1-9开头的一个(5位数-10位数),比如:12389,1345678
4.手机号码:要求:必须以13,14,15,18开头的11位数,比如13588889999
5.URL:如:https://www.bilibili.com/video/BV1fh411y7R8from=search&seid=183160912083761326

String regStr = "^[\u0391-\uffe5]+$";

String regStr1 = "^[1-9]\\d{5}$";

String regStr2 = "^[1-9]\\d{4,9}$";

String regStr3 = "^1[3|4|5|8]\\d{9}$";


String content4 = "https://www.bilibili.com/video/BV1fh411y7R8?from=search&seid=183160912083761326";

String regStr4 = "^([https|http]://)(([\\w-]+\\.)+[\\w])+(\\/[\\w-?=&/%.#]*)?$";

常用类
Pattern类

Pattren 对象是一个正则表达式对象,Pattren类没有公共构造方法,要创建一个Pattern 对象,调用其公共静态方法,它返回一个Pattern 对象,该方法接收一个正则表达式作为它的一个参数,比如:Pattern r = Pattern.compile(pattern)

Pattern类的方法 matches,整体匹配,看content的内容,是否符合regStr的规则,有点类似 ^ $
 

String content = "hello abc hello 韩顺平教育";
String regStr = "hello";
String regStr = "hello.*";//true
boolean matches = Pattern.matches(regStr,content);
sout("整体匹配="+matches);//false

Matcher 

PattrenSyntaxException

PatternSyctaxEcxeption是一个非强制异常类,它表示一个正则表达式模式中的语法错误

反向引用

给你一段文本,请你找出所有四个数字连在一起的子串,并且这四个数字要满足第一位和低四位相同,第二位和第三位相同,比如:1221,5775…

要解决前面的问题,我们需要了解正则表达式的几个概念:

分组:我们可以用圆括号组成一个比较复杂的匹配模式,那么一个圆括号的部分我们可以看做是一个子表达式/分组
捕获:把正则表达式中子表达式/分组匹配的内容,保存到内存中以数字编号或显式命名的组名,方便后面引用,从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推,组0表示的是整个正则式
反向引用:圆括号的内容被捕获后,可以在这个括号后被使用,从而写出一个比较实用的匹配模式,这个我们称为反向引用,这种引用既可以式在正则表达式内部,也可以是在正则表达式外部,内部反向引用\\分组号,外部反向引用¥分组号

去重案例

//老韩思路:先把点去掉
        //String regStr = "\\.+"
        //再把重复的 . 去掉
        String content = "我...我要...学学学学...编程java!";
        //String regStr1 = "(.)\\1{2,}";//我.我要.学.编程java!
        String regStr = "\\.+";//我.我要.学.编程java!
        Pattern pattern = Pattern.compile(regStr);
        Matcher matcher = pattern.matcher(content);
        while(matcher.find()){
            content = matcher.replaceAll("");
            System.out.println(content);
        }
        String regStr1 = "(.)\\1+";//我.我要.学.编程java!
        Pattern pattern1 = Pattern.compile(regStr1);
        Matcher matcher1 = pattern1.matcher(content);
        while(matcher1.find()){
            content = matcher1.replaceAll("$1");
            System.out.println(content);
        }


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值