加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

神秘的正则表达式

发布时间:2020-12-13 22:05:41 所属栏目:百科 来源:网络整理
导读:正则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE)。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些匹配某个模式的文本。(维基百科) 目前,正则

正则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE)。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些匹配某个模式的文本。(维基百科)

目前,正则表达式的应用很广泛,例如当我们当我们登录某应用的时候,会判断登录的账号是不是一个手机号,是不是邮箱,或者当我们注册某应用账号的时候检查密码强度,或者检测密码设置必须为数字和字母组合,又或者判断某个输入IP是不是一个有效IP地址等等。(现在验证 邮箱、手机号、密码、身份证号很常见)那么此时正则表达式就发挥了很大的作用。

初识正则表达式

代码 解释
b 匹配单词的开始或结束
. 匹配除换行符以外的任意字符
d 匹配数字
w 匹配字母或数字或下划线或汉字
^ 匹配字符串的开始
$ 匹配字符串的结束
s 匹配任意的空白符
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,m} 重复n次到m次
W 匹配任意不是字母,数字,下划线,汉字的字符
S 匹配任意不是空白符的字符
D 匹配任意非数字的字符
B 匹配不是单词开头或结束的位置
[^A] 匹配除了A以外的任意字符
[^ABCDE] 匹配除了ABCDE这几个字母以外的任意字符
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复

应用

java正则表达式通过java.util.regex包下的Pattern类与Matcher类实现.
Pattern类用于创建一个正则表达式,也可以说创建一个匹配模式,它的构造方法是私有的,不可以直接创建,但可以通过Pattern.complie(String regex)简单工厂方法创建一个正则表达式,Matcher对象是对输入字符串进行解释和匹配操作的引擎。与Pattern类一样,Matcher也没有公共构造方法。你需要调用Pattern对象的matcher方法来获得一个Matcher对象。compile参数是正则表达式,matcher参数是要匹配的字符串

Pattern pattern=Pattern.compile("");
        //Pattern.compile("",Pattern.CASE_INSENSITIVE);可以忽略大小写匹配
        Matcher matcher=pattern.matcher("");
        boolean b=matcher.matches();
       //boolean b=Pattern.matches(regex,input);

问题:Invalid escape sequence (valid ones are b t n f r ” ’ ),当我们写正则表达式式时若出现上面异常, 根据Java Language Specification 的要求,Java 源代码的字符串中的反斜线 被解释为Unicode 转义或其他字符转义。因此必须在字符串字面值中使用两个反斜线

matcher.find()和 matcher.matches()的区别

  • find:(部分匹配)

    Attempts to match the entire region against the pattern.
    If the match succeeds then more information can be obtained via the start,end,and group methods. return true if,and only if,the entire region sequence matches this matcher’s pattern
    尝试查找与该模式匹配的输入序列的下一个子序列。
    此方法从匹配器区域的开头开始,如果该方法的前一次调用成功了并且从那时开始匹配器没有被重置,则从以前匹配操作没有匹配的第一个字符开始。
    如果匹配成功,则可以通过 start、end 和 group 方法获取更多信息。
    返回:
    当且仅当输入序列的子序列匹配此匹配器的模式时才返回 true。

  • matches:(全局匹配)

    Attempts to match the entire region against the pattern.
    If the match succeeds then more information can be obtained via the start,and group methods.
    @return true if,the entire region sequence matches this matcher’s pattern
    尝试将整个区域与模式匹配。
    如果匹配成功,则可以通过 start、end 和 group 方法获取更多信息。
    返回:
    当且仅当整个区域序列匹配此匹配器的模式时才返回 true。

    注意:如果用同一个matcher对象,find()和matches()调用先后顺序不同,返回值不同,通过源码看到的

    public boolean matches() {
        return match(from,ENDANCHOR);
    }
        boolean match(int from,int anchor) {
        this.hitEnd = false;
        this.requireEnd = false;
        from        = from < 0 ? 0 : from;
        this.first  = from;
        this.oldLast = oldLast < 0 ? from : oldLast;
        for (int i = 0; i < groups.length; i++)
            groups[i] = -1;
        acceptMode = anchor;
        boolean result = parentPattern.matchRoot.match(this,from,text);
        if (!result)
            this.first = -1;
        this.oldLast = this.last;
        return result;
    }
    
    
    
    public boolean find() {
        int nextSearchIndex = last;
        if (nextSearchIndex == first)
            nextSearchIndex++;
    
        // If next search starts before region,start it at region
        if (nextSearchIndex < from)
            nextSearchIndex = from;
    
        // If next search starts beyond region then it fails
        if (nextSearchIndex > to) {
            for (int i = 0; i < groups.length; i++)
                groups[i] = -1;
            return false;
        }
        return search(nextSearchIndex);
    }
    boolean search(int from) {
        this.hitEnd = false;
        this.requireEnd = false;
        from        = from < 0 ? 0 : from;
        this.first  = from;
        this.oldLast = oldLast < 0 ? from : oldLast;
        for (int i = 0; i < groups.length; i++)
            groups[i] = -1;
        acceptMode = NOANCHOR;
        boolean result = parentPattern.root.match(this,text);
        if (!result)
            this.first = -1;
        this.oldLast = this.last;
        return result;
    }

    通过上面源码发现, 由于两个匹配方法中this.oldLast = this.last;执行的先后顺序就导致oldLast数值不同,继而执行下一个不同方法就会根据oldLast 值做匹配,则先后顺序就会导致返回值不同的情况。如果想消除两个方法之间的影响可以调用matcher.reset();重置状态

group.start.end用法解析

String str = "my name is xiehui.";
    Pattern pattern = Pattern.compile("x(w+)(.)");
    Matcher matcher = pattern.matcher(str);
    int lon = matcher.groupCount();// 此处值返回的是2,他不是最终匹配的结果数,他只是子模式匹配的结果数,一般情况下子模式有几个,他就是几
    while (matcher.find()) {
        System.out.println("Group 0:" + matcher.group(0));// 得到第0组——整个匹配
        System.out.println("Group 1:" + matcher.group(1));// 得到第一组匹配——与(w+)匹配的
        System.out.println("Group 2:" + matcher.group(2));// 得到第二组匹配——与(.)匹配的,组也就是子表达式
        System.out.println("Start 0:" + matcher.start(0) + " End 0:"
                + matcher.end(0));// 总匹配的索引
        System.out.println("Start 1:" + matcher.start(1) + " End 1:"
                + matcher.end(1));// 第一组匹配的索引
        System.out.println("Start 2:" + matcher.start(2) + " End 2:"
                + matcher.end(2));// 第二组匹配的索引
        System.out.println(str.substring(matcher.start(0),matcher.end(1)));// 从总匹配开始索引到第1组匹配的结束索引之间子串——xiehui.
        System.err.println("replaceAll : "+matcher.replaceAll("222221"));//不改变原始字符串str,返回值是替换后的新字符串
    }

返回值为:
Group 0:xiehui.
Group 1:iehui
Group 2:.
Start 0:11 End 0:18
Start 1:12 End 1:17
Start 2:17 End 2:18
xiehui
replaceAll : my name is 222221

通过上面发现group返回的是子分组的匹配,groupCount();只是子模式匹配的结果数,一般情况下子模式(用小括号表示部分)有几个,它就是几,group(0)是表示全匹配,group(1)表示第一个分组匹配部分,以此类推,start(i)和end(i)返回的值就是group(i)的的开始索引和结束索引。
matcher.replaceAll :不改变原始字符串str,返回值是替换后的新字符串

常用的正则表达式

  • 是否为IPV4地址
((2[0-4]d|25[0-5]|[01]?dd?).){3}(2[0-4]d|25[0-5]|[01]?dd?)
  • 验证身份证
(^[1-9]d{14}$)|(^[1-9]d{16}([0-9]|X)$)
  • 校验密码
    密码长度不低于6位,不能为特殊字符只能为大小写字母或者数字组合
^[a-zA-Z0-9]{6,}$
  • 验证邮箱
>^([a-z0-9A-Z]+[_|-|.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?.)+[a-zA-Z]{2,}$
  • 校验手机号
    匹配13*,145,147,15*,176,177,18*号段手机号,若有当前运营商号段没有考虑到,自己添加
^(13[0-9]|14[5|7]|15d|17[6|7]|18[d])d{8}$

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读