美文网首页
正则表达式(JAVA版)

正则表达式(JAVA版)

作者: Zhang小二 | 来源:发表于2019-04-13 23:56 被阅读0次

    前言

    在编程中,处理字符时,简单的直接使用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版)

          本文链接:https://www.haomeiwen.com/subject/pojkwqtx.html