zoukankan      html  css  js  c++  java
  • Java正则表达式简明教程


    本文的大部分内容转载自正则表达式从入门到实战,内容按照自己的风格进行了排版。


    什么正则表达式

    正则表达式(Regular Expression)可以理解为是对一种文本匹配规则的描述。正则表达式的主要作用是用来检索、匹配或替换那些符合某个(规则)模式的文本内容。比如我们要检查一个字符串是不是一个合法的邮箱,或者是不是一个合法的身份证时都可以使用正则表达式来匹配。

    普通字符

    普通字符主要指:字母[a-zA-Z]、数字[0-9]、下划线[-]、汉字,标点符号等。对于普通字符可以使用方括号表达式。如下:

    但是,特殊字符(除了小尖角“^”和中划线“-”外)被包含到方括号中,就会失去特殊意义,只代表其字符本身。比如[d.+] 匹配0-9的任意一个数字或者小数点“.”或者加号“+”。也就是说d在自定义集合中仍然表示数字,但是小数点在字符集合中只表示小数点本身,而不是除“ ”之外的任何单个字符。

    预定义字符

    这类预定义字符可以匹配依赖字符。比如d就可以匹配0-9这10个数字字符,使用起来比较方便。如果要匹配包括" "在内的所有字符,一般用[sS]

    特殊字符

    特殊字符在正则表达式中表示特殊的含义,比如:*,+,?,,等等。

    除了上面的特殊字符外{}花括号也是一个特殊字符,当我们需要匹配上面这些特殊字符本身的时候,比如说要匹配/这个符号本身,我们要加上转义符号'/',所以我们需要使用//来匹配/本身,其他的特殊字符也是如此。

    数量限定字符

    限定字符又叫量词,是用于表示匹配的字符数量的。

    比如a(bc)* 可以匹配a,abc和abcbc等字符串。

    定位字符

    定位字符也叫字符边界,标记匹配的不是字符而是符合某种条件的位置,所以定位字符是“零宽的”。

    常用的定位字符

    匹配这样一个位置:前面的字符和后面的字符不全是w。

    选择符和分组

    |可以定义两个匹配规则,一个字符串只要满足其中一个规则就会被匹配上。d{5}-d{4}|d{5}这个表达式用于匹配美国的邮政编码。美国邮编的规则是5位数字,或者用连字号间隔的9位数字。之所以要给出这个例子是因为它能说明一个问题:使用分枝条件时,要注意各个条件的顺序。如果你把它改成d{5}|d{5}-d{4}的话,那么就只会匹配5位的邮编(以及9位邮编的前5位)。原因是匹配分枝条件时,将会从左到右地测试每个条件,如果满足了某个分枝的话,就不会去再管其它的条件了。

    我们已经提到了怎么重复单个字符(直接在字符后面加上限定符就行了);但如果想要重复多个字符又该怎么办?你可以用小括号来指定子表达式(也叫做分组),然后你就可以指定这个子表达式的重复次数了,你也可以对子表达式进行其它一些操作。另外,括号中的表达式匹配到的内容会存储起来,并可以获取到括号中表达式匹配到的内容。每一对括号会分配一个编号,使用( )的捕获根据左括号的顺序从1开始自动编号,编号为0的捕获是整个正则表达式匹配到的文本。

    (d{1,3}.){3}d{1,3}是一个简单的IP地址匹配表达式。不幸的是,它也将匹配256.300.888.999这种不可能存在的IP地址。但是在Java中可以先匹配这样一个简单的IP地址,然后在使用split函数分隔,如果有大于255的数字则是一个非法的IP。

    反向引用

    通过反向引用,可以对分组已捕获的字符串进行引用。“ umber” 中的 number 就是组号

    预搜索

    预搜索,又叫零宽断言,又叫环视,它是对位置的匹配,与定位字符(边界字符)类似。

    运算符的优先级

    正则表达式从左到右进行计算,并遵循优先级顺序,这与算术表达式非常类似。下表的优先级从高到低排序。

    常用正则

    • 匹配中文: [1]{0,}$
    • 判断密码是否是强密码:强密码(必须包含大小写字母和数字的组合,可以使用特殊字符,长度在8-10之间):^(?=.d)(?=.[a-z])(?=.*[A-Z]).{8,10}$
    • 提取验证码

    下面是使用正则表达式提取验证码的代码

    public class RegexDemo {
    
    
        public static void main(String[] args) {
            List<String> inputList = new ArrayList<String>(16);
            inputList.add("【京东】尊敬的用户,634561是您本次的省份验证码,30分钟内有效,请完成验证。");
            inputList.add("滴滴】您的验证码是6678,请在页面中提交验证码完成验证。");
            inputList.add("【百度】376687(动态验证码),请在30分钟内填写。");
            String regex = "(?:验证码\D*(\d{4}|\d{6}))|(?:(\d{4}|\d{6})\D*验证码)";
            Pattern pattern = Pattern.compile(regex);
            System.out.println("一键获取到的验证码如下:");
            for (String input : inputList) {
                Matcher matcher = pattern.matcher(input);
                if (matcher.find()) {
                    //可以进行替换
                    for (int i = 1; i <= matcher.groupCount(); i++) {
                        if (matcher.group(i) != null) {
                            System.out.println(matcher.group(i));
                        }
                    }
                }
            }
        }
    
    
    

    附录

    公众号推荐

    欢迎大家关注我的微信公众号「程序员自由之路」


    1. u4e00-u9fa5 ↩︎

  • 相关阅读:
    PS后期合成,你和大神的差距就这5步!
    欧几里得算法:从证明等式gcd(m, n) = gcd(n, m mod n)对每一对正整数m, n都成立说开去
    谜题:过桥问题
    《世界是数字的》读书笔记第一部分_硬件篇
    完全偶图K(3,3)与完全图K5是否存在平面表示
    Dijkstar算法的数学原理
    LeetCode 141. Linked List Cycle
    LeetCode 155. Min Stack
    LeetCode 160. Intersection of Two Linked Lists
    LeetCode 165.Compare Version Numbers
  • 原文地址:https://www.cnblogs.com/54chensongxia/p/11575125.html
Copyright © 2011-2022 走看看