栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java正则表达式(Regular Express)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java正则表达式(Regular Express)

目录

第一个例子

正则表达式的底层实现

正则表达式语法

字符匹配符

选择匹配符

限定符

定位符

捕获分组

非命名捕获

命名捕获

非捕获分组(特别分组)

非贪婪捕获

正则表达式应用

正则表达式三个常用的类

概述

pattern

matcher

反向引用


第一个例子
package dao.impl;

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


public class Regexp {

    public static void main(String[] args) {
        //假设,编写了爬虫,从百度页面得到如下文本
        String content = "建国初期,我们在小学教科书中崇拜那些为国家做出巨大贡献的人。来自黄继光、邱少云、雷锋和其他人的故事是必不可少的。" +
                "他们要么为新中国流血,要么为新中国的早期建设做出了巨大贡献。这自然值得学习。许多英雄故事被囊括在教科书中,供孩子们study。" +
                "但在此案中,一名man故意杀人,却以卑鄙的方式把自己打造成“人民英雄”,还登上了小学教科书。" +
                "这个人叫刘学保。他看到了一个流传广泛的英雄故事,觉得这种受到尊重和钦佩的感觉特别好。从此他开始走向邪恶的道路,依靠预谋杀人来伪造证据。" +
                "他把自己伪装成人民英雄,也受到人们的钦佩。然而,经过four year的研究和专家的考察,他的谎言最终弄巧成拙,成为了历史上的罪人,永远逃脱不掉杀人凶手的身份";
        //提取文章中的单词
        //1.传统方法。使用遍历方式,代码量大,效率不高。
        //2.正则表达式技术

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

    }
}

为什么要学习正则表达式?

1.处理文本的利器

2.登录界面的密码,账号,邮箱,手机号码等的验证 

正则表达式的底层实现
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegTheory {
    public static void main(String[] args) {
        String context = "1998建国初期,我们在小学教科书中崇拜那些为国家做出巨大贡献的人。来自黄继光、邱少云、雷锋和其他人的故事是必不可少的。" +n" +
                "                "他们要么为新中国流血,要么为新中国的早期建设做出了巨大贡献。这自然值得学习。许多英雄故事被囊括在教科书中,供孩子们study。" +n" +
                "                "但在此案中,一名man故意杀人,却以卑鄙的方式把自己打造成“人民英雄”,还登上了小学教科书。" +n" +
                "                "这个人叫刘学保。他看到了一个流传广泛的英雄故事,觉得这种受到尊重和钦佩的感觉特别好。从此他开始走向邪恶的道路,依靠预谋杀人来伪造证据。" +n" +
                "                "他把自1111己伪装成人民英雄,也受到人们的钦佩。然而,经过four year的研究和专家的考察,他的谎言最终弄巧成拙,成为了历史上的罪人,永远逃脱不掉杀人凶手的身份";
        //匹配规则匹配所有的四个数字
        String regString = "\d\d\d\d";
        //创建模式对象
        Pattern pattern = Pattern.compile(regString);
        //创建匹配器matcher,按照正则表达式的规则,去匹配content字符串
        Matcher matcher = pattern.matcher(context);
        //开始匹配
        while(matcher.find()){
            System.out.println(matcher.group(0));
        }
    }
}

matcher.find() 完成的任务(考虑分组):

什么是分组?

String regString = "(\d\d)(\d\d)";

group函数传值(0或者1或者2.............)这涉及到分组,正则表达式中有()表示分组,第一个()表示第一组,第二个()表示第二组。

1.根据指定的规则,来定位满足规则的子字符串(比如1998)

2.找到后,将子字符串的开始的索引记录到matcher对象的int[]  group属性中(如果之前执行过一次,下一次就会清空该数组,可以又下面断点调试证明)

        2.1 把该子字符串开始的索引记录到group[0] = 0,;把该子字符串的结束的索引+1的值记录到group[1]=4

        2.2 记录1组()匹配到的字符串group[2] = 0; group[3] = 2

        2.3 记录2组()匹配到的字符串group[4] =2;group[5] = 4; 

        2.4 如果有更多的分组。。。。,可以继续

3.同时记录oldlast的值为子字符串的结束的索引+1值为4,即下次执行find时候就从4开始匹配

group方法的源码

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();
    }

在while(matcher.finder())处设置断点,根据以上原理可以看出每次都会清空group数组。

group函数传值(0或者1或者2.............)这涉及到分组,正则表达式中有()表示分组,第一个()表示第一组,第二个()表示第二组以此类推。

正则表达式语法

基本介绍:如果想要灵活使用正则表达式,必须了解其中各种元字符的功能,元字符从功能上大致分为:

1.限定符

2.选择匹配符

3.分组组合和反向引用符

4.特殊字符

5..字符匹配符

6.定位符

元字符-转义号:当我们使用正则表达式去检索某些特殊符号的时候,需要使用到转义符号,如果不使用则报错。需要使用转义符号的字符有   . *+()$/?[]^{}-

java中转义字符要用\

package dao.impl;

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

public class Se {
    public static void main(String[] args) {
        String context = "abc$(abc(123(";
        //匹配(
        String regex = "\(";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(context);
        while(matcher.find()){
            System.out.println(matcher.group(0));
        }
    }
}

字符匹配符
符号含义实例解释
[]可接收的字符列表[efgh]efgh任意一个字符,[.]表示就是.本身.
[^]不可接收的字符列表[^abc]除abc之外的任意一个字符,包括数字和特殊字符
-连字符A-Z任意单个大写字母
符号含义示例说明匹配输入
.匹配除n以外的任何字符a..b以a开头,b结尾中间包括两个任意的字符串aaab,abcb
\d匹配单个数字字符\d{3}(\d)?包含三个或者四个数字的字符串123,6789
\D匹配单个非数字字符,相当于[^0-9]\D(\d)*以单个非数字字符开头,后接任意个数字字符串a,A332
\w匹配单个数字,大小写字母字符串,相当于[0-9a-zA-Z]\d{3}\w{4}以三个数字字符开头长度为7的数字字母字符串234abcd,12345Pe
\W匹配单个不为数字,大小写字母字符,相当于[^0-9a-zA-Z]

\W+\d{2}

+代表一个或者多个

以至少以一个非数字字母字符开头,2个数字字符结尾的字符串#29,#?@10
\s匹配任何空白字符(空格,制表符)
\S匹配任何非空白字符,和s刚好相反
.匹配出n之外的所有字符,如果是要本身则\.

字符匹配案例

可以利用(?i)不区分大小写

(?i)abc 表示abc都不区分大小写

a(?i)bc表示bc不区分大小写

a((?i)b)c只有b不区分大小写

选择匹配符

在匹配某个字符串的时候是选择性的,即:既可以匹配这个,又可以匹配那个,这个时候你就需要用到选择匹配符号.

符号符号示例解释
|匹配"|"之前或者之后的表达式ab|cdab或者cd

限定符

用于指定其前面的字符和组合项连续出现多少次

java匹配是一种贪婪匹配,尽量匹配多的

符号含义示例说明匹配输入
*

指定字符重复0次或n次

(abc)*仅包含任意个abc的字符串,等效于w*abc,abcabcabc
+指定字符重复1次或者n次m+(abc)*至少以一个m开头,后接任意个abc的字符串m,mabc,mabcabc
?指定字符重复0次或者1次

m+abc?

(没有把abc括起来,就是只作用于c)

以至少1个m开头,后接ab或者abc的字符串mab,mabc,mmmab,mmabc
{n}只能输入n个字符[a-c]{3}由abcd中字母组成的任意长度为3的字符串

abc,dbc

,adc等

{n,}指定至少n个匹配[abcd]{3,}由abcd中字母组成的任意长度不小于3的字符串aab,dbc,aaabdc
{n,m}指定至少n个但不多于m个匹配(java匹配是一种贪婪匹配,尽量匹配多的)[abcd]{3,5}由abcd中字母组成不小于3长度,不大于5长度的字符串abc,abcd

定位符
符号含义示例说明匹配输入
^以指定字符开始^[0-9]+[A-Z]*至少以一个数字打头,后接任意个小写字母的字符串123,66a
$以指定字符结束^[0-9]\-[a-z]+$以一个数字开头后接连字符"-",并以至少一个小写字母结尾的字符串1-a
\b匹配目标字符串的边界han\b这里说的字符串边界是指子串间有空格,或者目标字符串的结束位置

hanshunpin

sphan shan(加粗部分被匹配到了)

\B匹配目标字符串的非边界han\B和\b的含义刚刚好相反

hanshunpin

sphan shan(加粗部分被匹配到了)

捕获分组
常用分组构造形式说明
(pattern)非命名捕获,捕获匹配的子字符串。编号为0第一个捕获是由整个正则表达式模式匹配的文本,其他捕获结果则根据左括号顺序从1开始自动编号。
(?pattern)命名捕获,这种分组方式捕获的字符串既可以通过编号来获取,也可以通过组名来获取

非命名捕获
package dao.impl;

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

public class Se {
    public static void main(String[] args) {
        String context = "hanshunpiping s1234 nn1998ha";
        //匹配(
        String regex = "(\d\d)(\d\d)";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(context);
        while(matcher.find()){
            System.out.println(matcher.group(0));
            System.out.println(matcher.group(1));
            System.out.println(matcher.group(2));
        }
    }
}

命名捕获
package dao.impl;

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

public class Se {
    public static void main(String[] args) {
        String context = "hanshunpiping s1234 nn1998ha";
        //匹配(
        String regex = "(?\d\d)(?\d\d)";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(context);
        while(matcher.find()){
            System.out.println(matcher.group(0));
            System.out.println(matcher.group("g1"));
            System.out.println(matcher.group("g2"));
//也可以通过
            System.out.println(matcher.group(1));
            System.out.println(matcher.group(2));
        }
    }
}

非捕获分组(特别分组)
常用分组构造形式说明
(?:pattern)匹配pattern但是不捕获该匹配的子表达式,即他是一个非捕获匹配。例如:industry|industries 可以写成industr(?:y|ies)。
(?=pattern)它是一个非捕获匹配windows(?=95|98|NT|2000)匹配windows2000中的windows,但是不匹配windows3.1中的windows
(?!pattern)例如:windows(?!95|98|NT|2000)不匹配windows2000中的windows,但是匹配windows3.1中的windows

非贪婪捕获

java正则表达式默认贪婪捕获,但是我们也可以设置成非贪婪捕获。

当?紧跟*+?{n}{n,}{n,m}之后时候就是非贪婪匹配

package dao.impl;

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

public class Se {
    public static void main(String[] args) {
        String context = "hanshunpiping s111111111111 nn1998ha";
        //匹配(
        String regex = "\d+?";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(context);
        while(matcher.find()){
            System.out.println(matcher.group(0));
        }
    }
}

正则表达式应用

验证汉字

package dao.impl;

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

public class Se {
    public static void main(String[] args) {
        //汉字
        String context = "疯狂胜多负少发射点发射点发啊啊啊啊啊啊啊啊啊啊";
        String regex = "^[\u4e00-\u9fa5]+$";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(context);
        while(matcher.find()){
            System.out.println(matcher.group(0));
        }
    }
}

验证邮箱

package dao.impl;

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

public class Se {
    public static void main(String[] args) {
        //邮箱
        String context = "3455488858@qq.com";
        String regex = "^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(context);
        if(matcher.find()){
            System.out.println("YES");
        }else{
            System.out.println("NO");
        }
    }
}

验证url

package dao.impl;

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

public class Se {
    public static void main(String[] args) {
        //url
        String context = "https://blog.csdn.net/cjx529377/article/details/78287552?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163357292916780271538553%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=163357292916780271538553&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-78287552.pc_search_result_control_group&utm_term=%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%BD%AC%E4%B9%89%E5%AD%97%E7%AC%A6&spm=1018.2226.3001.4187";
        String regex = "^((http|https):\/\/)([\w]+\.)+[\w]+(\/[\w]+)*\/([\w?_~&%=.-/])*$";
        Pattern pattern = Pattern.compile(regex);
        System.out.println(Pattern.matches(regex,context));

    }
}

正则表达式三个常用的类

概述

pattern,Matcher,patternSyntaxException

pattern对象是一个正则表达式对象。pattern类没有公共的构造方法,创建对象就调用其公共的静态方法,返回一个pattern对象    Pattern pattern = Pattern.compile(regex表达式);

matcher

Matcher对象是对输入字符串进行解释和匹配的引擎

patternSyntaxException对象是一个非强制的异常类,对正则表达式语法错误进行抛异常

pattern

matcher方法用于整体匹配,可以去掉定位符,因为之前不是整体匹配,a111要被111匹配就需要定位符,说明起始位置。现在是整体匹配就不需要。pattern的matches方法底层调用matcher的matches方法

public class Se {
    public static void main(String[] args) {
        //邮政编码
        String context = "https://blog.csdn.net/m0_57652176?spm=1018.2226.3001.5343";
        String regex = "h.*";
        Pattern pattern = Pattern.compile(regex);
        System.out.println(Pattern.matches(regex,context));
    }
}

matcher

package dao.impl;

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

public class Se {
    public static void main(String[] args) {
        //url
        String context = "hello edu jack tom hello smith hello";
        String regex = "hello";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(context);
        while (matcher.find()){
            System.out.println("===================");
            System.out.println(matcher.start());
            System.out.println(matcher.end());
            System.out.println(context.substring(matcher.start(),matcher.end()));
        }
        //整体匹配判断某个字符串是否满足规则
        boolean matches = matcher.matches();
        System.out.println(matches);
        String all = matcher.replaceAll("李祖德");
        System.out.println(all);
    }
}

反向引用

圆括号的内容被捕获后,可以在这个括号后面使用,这就是反向引用。

匹配两个连续的相同数字:(\d)\1

匹配五个连续相同数字:(\d)\1{4}

匹配千位与个位相同,百位与十位相同.5225:(\d)(\d)\2\1

前面是五位数,然后一个-,然后九位数,连续的每三位要相同。

\d{5}-(\d)\1{2}(\d)\2{2}(\d)\3{2}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/302234.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号