正则表达式(JAVA版)

前言

在编程中,处理字符时,简单的直接使用match、find等方法即可。稍微复杂点的,就需要使用正则表达式进行处理了。正则表达式虽然在各语言中有所差异,但总体是差不多的,而且根据二八法则,只需要学习常见的20%的语法就可以解决工作中大部分的字符处理问题。
如果想作深入学习,有本书推荐给大家《精通正则表达式*第三版》。
本文只对java中常见的正则表达式进行简单记录,之所以用java,是因为左耳老师一直说java是必学语言,java非我工作的常用语言,要学好非熟用不可得也。

一、正则基础

常见匹配符回顾:

表达式 含义 备注
^ 行或字符串的起始
$ 行或字符串的结束
. 任意字符(不包括行结束符)
[...] 匹配“字符集” [0-9]、[a-z]
[^...] 不匹配“字符集”
(...) 捕获分组
(?:...) 括号不捕获分组
|
* 零个或多个 相当于{0,}
+ 一个或多个 相当于{1,}
? 零个或一个 相当于{0,1}
{m,n} 至少m个但不多于n个匹配
{m} m个匹配,实际上多于m个也可以匹配,但若是捕获只会捕获m个
{m,} m个以上匹配
{,n} 最多n个匹配
? 非贪婪模式,即最小匹配即可,缺省是贪婪模式
\w 任意字母字符
\W 非单词字母字符
\d 数字字符
\D 非数字字符
\s 空格、制表符等 由java.lang.Character.isWhitespace()决定
\S 非空格字符

当然,还有一些正则正反向位置匹配符没有列出来,虽然不常用,但偶尔也会用到。

二、使用方法

java中主要使用java.util.regex包中的Pattern、Matcher两个包进行处理,方法也比较多而全,详细方法可以直接检查api文档。
就个人而言,对于一项技术,除非本身非常简短才会通览其所有的使用方法;否则,只会从实际应用的场景触发,先了解目前应该用到的方法,随着以后应用场景的不同再做深入学习。毕竟人的精力和大脑的记忆容量是有限的。

常见应用场景有:

  • 判断字符串是否匹配某个条件
        //判断某IP地址是否符合IPv4格式(简单判断,不作范围判断):
        String ip = "127.0.0.1";
        if (Pattern.matches("\\d+\\.\\d+\\.\\d+\\.\\d+", ip)) {
            System.out.println(ip + ":格式正确");
        }

        // 不区分大小写的匹配
        String str = "Abc";
        Pattern p = Pattern.compile("abc",Pattern.CASE_INSENSITIVE);
        if(p.matcher(str).lookingAt()) {
            System.out.println("match!");
        }

        // 不区分大小写的匹配,方法二
        String str = "Abc";
        if(Pattern.matches("(?i)abc",str)) {
            System.out.println("match!");
        }

在这里,需要注意以下matches和lookingAt方法的区别,两者都是尝试匹配正则,但matches要求整个字符串都匹配,则lookingAt不需要(字符串内部分匹配即可),但lookingAt需要从第一个字符开始匹配。
相比之前,感觉还是find更实用,matches相当于缺省加了^regex$,lookingAt相当于缺省加了^regex。

  • 若字符串匹配某个条件,则获取其具体匹配的值
        //查询根目录的剩余空间和使用率
        String lines = "$ df -k\n" +
                "文件系统                 1K-块      已用      可用 已用% 挂载点\n" +
                "/dev/sda1             26206076  24555196    319680  99% /\n" +
                "/dev/sda2            31684544  30006348     68676 100% /data";
        Pattern r = Pattern.compile("\\d+\\s+\\d+\\s+(\\d+)\\s+(\\d+%)\\s+/$");
        for (String line : lines.split("\n")) {
            Matcher m = r.matcher(line);
            if (m.find()) {
                System.out.println("根目录剩余空间:" + m.group(1) + "k,当前利用率:" + m.group(2));
            }
        }

        //获取字符串中所有匹配的值
        String nums = "123 111 478 999 666";
        Pattern p = Pattern.compile("(\\d+)");
        Matcher m = p.matcher(nums);
        int count = 0;
        while (m.find()) {
            count++;
            System.out.println("匹配到的第" + count + "个数字为:" + m.group(1));
        }
  • 替换字符、切分字符
    切分字符使用String.split(regex)即可实现切分。
    替换字符使用String.replace(regex)、replaceFirst、replaceAll实现替换。
        // 将dog替换成cat
        String str = "The dog says 666.";
        Matcher m = Pattern.compile("dog").matcher(str);
        str = m.replaceFirst("cat");
        System.out.println(str);
  • 反向引用
    反向引用主要用在替换场景中,在替换的字符中引用了前文匹配到的字符内容。
        // 将and前后的内容置换
        String str = "dog and cat";
        Matcher m = Pattern.compile("(\\S+)\\s+and\\s+(\\S+)").matcher(str);
        str = m.replaceFirst("$2 and $1");
        System.out.println(str);
  • 动态正则
    动态正则主要是指正则表达式非源码定义,而是引用外部规则,比如db中,使用也是比较简单,主要需要注意一下判断是否存在编译异常。

总结

1.java中使用正则表达式还是比较简单的,跟perl5比较类似,差别不大。
2.本文只是简单介绍,抛砖引玉,在实际应用中,还是需要考虑周全,正则不止需要达到匹配要求,同样需要考虑各种边界情况。此外,还需要考虑正则的解析效率问题。

你可能感兴趣的:(正则表达式(JAVA版))