Java正则表达式简明教程


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


什么正则表达式

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

普通字符

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

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

预定义字符

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

特殊字符

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

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

数量限定字符

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

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

定位字符

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

常用的定位字符

\b匹配这样一个位置:前面的字符和后面的字符不全是\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。

反向引用

通过反向引用,可以对分组已捕获的字符串进行引用。“\number” 中的 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 ↩︎

posted @ 2019-09-23 21:55  程序员自由之路  阅读(118)  评论(0编辑  收藏