阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

分组匹配

28次阅读
没有评论

共计 1985 个字符,预计需要花费 5 分钟才能阅读完成。

我们前面讲到的 (...) 可以用来把一个子规则括起来,这样写 learn\s(java|php|go) 就可以更方便地匹配长字符串了。

实际上 (...) 还有一个重要作用,就是分组匹配。

我们来看一下如何用正则匹配 区号 - 电话号 码这个规则。利用前面讲到的匹配规则,写出来很容易:

\d{3,4}\-\d{6,8}

虽然这个正则匹配规则很简单,但是往往匹配成功后,下一步是提取区号和电话号码,分别存入数据库。于是问题来了:如何提取匹配的子串?

当然可以用 String 提供的 indexOf()substring()这些方法,但它们从正则匹配的字符串中提取子串没有通用性,下一次要提取 learn\s(java|php) 还得改代码。

正确的方法是用 (...) 先把要提取的规则分组,把上述正则表达式变为(\d{3,4})\-(\d{6,8})

现在问题又来了:匹配后,如何按括号提取子串?

现在我们没办法用 String.matches() 这样简单的判断方法了,必须引入 java.util.regex 包,用 Pattern 对象匹配,匹配后获得一个 Matcher 对象,如果匹配成功,就可以直接从 Matcher.group(index) 返回子串:

import java.util.regex.*;

public class Main {public static void main(String[] args) {Pattern p = Pattern.compile("(\\d{3,4})\\-(\\d{7,8})");
        Matcher m = p.matcher("010-12345678");
        if (m.matches()) {String g1 = m.group(1);
            String g2 = m.group(2);
            System.out.println(g1); // 010
            System.out.println(g2); // 12345678
        } else {System.out.println("匹配失败!");
        }
    }
}

运行上述代码,会得到两个匹配上的子串 01012345678

要特别注意,Matcher.group(index)方法的参数用 1 表示第一个子串,2 表示第二个子串。如果我们传入 0 会得到什么呢?答案是010-12345678,即整个正则匹配到的字符串。

Pattern

我们在前面的代码中用到的正则表达式代码是 String.matches() 方法,而我们在分组提取的代码中用的是 java.util.regex 包里面的 Pattern 类和 Matcher 类。实际上这两种代码本质上是一样的,因为 String.matches() 方法内部调用的就是 PatternMatcher类的方法。

但是反复使用 String.matches() 对同一个正则表达式进行多次匹配效率较低,因为每次都会创建出一样的 Pattern 对象。完全可以先创建出一个 Pattern 对象,然后反复使用,就可以实现编译一次,多次匹配:

import java.util.regex.*;

public class Main {public static void main(String[] args) {Pattern pattern = Pattern.compile("(\\d{3,4})\\-(\\d{7,8})");
        pattern.matcher("010-12345678").matches(); // true
        pattern.matcher("021-123456").matches(); // false
        pattern.matcher("022#1234567").matches(); // false
        // 获得 Matcher 对象:
        Matcher matcher = pattern.matcher("010-12345678");
        if (matcher.matches()) {String whole = matcher.group(0); // "010-12345678", 0 表示匹配的整个字符串
            String area = matcher.group(1); // "010", 1 表示匹配的第 1 个子串
            String tel = matcher.group(2); // "12345678", 2 表示匹配的第 2 个子串
            System.out.println(area);
            System.out.println(tel);
        }
    }
}

使用 Matcher 时,必须首先调用 matches() 判断是否匹配成功,匹配成功后,才能调用 group() 提取子串。

利用提取子串的功能,我们轻松获得了区号和号码两部分。

练习

利用分组匹配,从字符串 "23:01:59" 提取时、分、秒。

下载练习

小结

正则表达式用 (...) 分组可以通过 Matcher 对象快速提取子串:

  • group(0)表示匹配的整个字符串;
  • group(1)表示第 1 个子串,group(2)表示第 2 个子串,以此类推。

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-08-05发表,共计1985字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中