[Java]正则表达式详解

在Java中如果我们需要在大量的字符串中对特定格式的字符串进行查找、替换或者删除,正则表达式将是最好的选择。但是新手却并不擅长使用这一方法,因此本文将详细介绍一下正则表达式的相关用法。


1.如何使用正则表达式


Java在1.4版本新增了java.util.regex包提供对正则表达式的支持,其中Pattern类指正则表达式的编译表示形式,Matcher类指通过解释Pattern对字符序列执行匹配操作的引擎。当我们需要使用正则表达式匹配一个字符串时,可以使用如下方法:

//创建"abc"的模式实例
Pattern p = Pattern.compile("abc");
//使用"abc"的模式去匹配"abcdef"
Matcher m = p.matcher("abcdef");
其中compile方法还有一种重载形式compile(String regex, int flags),flags可以通过传入Pattern的常量设置一些特别的功能,比如CASE_INSENSITIVE可以设置不区分大小写。


获得Matcher对象实例后,便可以通过Matcher中的方法进行字符串的查找、替换或删除。


查找:matches() / lookingAt() / find()


matches方法用于判断字符串是否匹配该正则表达式,只有整个字符串完全匹配时才会返回true。例如:

Pattern p = Pattern.compile("abc");
Matcher m = p.matcher("abcdef");
System.out.println(m.matches());   //false
lookingAt方法用于判断字符串的起始是否匹配该正则表达式,只要该正则表达式的起始匹配则返回true。例如:

Pattern p = Pattern.compile("abc");
Matcher m = p.matcher("abcdef");
System.out.println(m.lookingAt());   //true
find方法用于查找字符串中匹配该正则表达式的子串,如果查找到了会返回true,并且在下一次查找时将会跳过已查找到的子串。例如:

Pattern p = Pattern.compile("abc");
Matcher m = p.matcher("abcdef");
System.out.println(m.find());   //true
System.out.println(m.find());   //false

替换:replaceFirst(String replacement) / replaceAll(String replacement) / appendReplacement(StringBuffer sb, String replacement) / appendTail(StringBuffer sb)


replaceFirst方法可以将字符串中首个匹配该正则表达式的子串替换为指定的字符串。例如:

Pattern p = Pattern.compile("abc");
Matcher m = p.matcher("abcdefabc");
System.out.println(m.replaceFirst("cba"));   //cbadefabc
replaceAll方法可以将字符串中所有匹配该正则表达式的子串替换为指定的字符串。例如:

Pattern p = Pattern.compile("abc");
Matcher m = p.matcher("abcdefabc");
System.out.println(m.replaceFirst("cba"));   //cbadefcba
appendReplacement方法支持非终端的添加和替换,他会把替换后的子串添加到指定的StringBuffer中,但是如果字符串的尾部不匹配则不会自动添加,需要使用appendTail方法手动添加。例如:

Pattern p = Pattern.compile("abc");
Matcher m = p.matcher("abcdefabcdef");
StringBuffer sb = new StringBuffer();
while (m.find()) {
    m.appendReplacement(sb, "cba");
}
System.out.println(sb);  //cbadefcba
m.appendTail(sb);
System.out.println(sb);   //cbadefcbadef


捕获:group() / group(int group) / groupCount()


group方法用于捕获匹配到的子串,如果在正则表达式中使用"()"可以将该正则表达式分组,在group方法的参数中填入分组的编号可以获得该组的数据,groupCount方法用于获得该正则表达式分组的组数。例如:

Pattern p = Pattern.compile("(a)(bc)");
Matcher m = p.matcher("abcdefabcdef");
while (m.find()) {
    for (int i=0; i<=m.groupCount(); i++) {
        System.out.println(m.group(i));
    }
}

2.如何编写正则表达式


我们可以认为正则表达式就是一串字符的排列规则或者模板,它一般由普通字符和特殊字符组成。所以在编写正则表达式前首先要记住所有的普通字符和特殊字符。


在字符之间加入"|"表示或者关系,比如"x | y"表示下一个字符x或者y均可。

当熟悉了字符的使用以后,我们发现能干的事情还是不多。因为许多匹配的字符你并不知道它会出现几次,所以我们需要数量词来控制字符出现的次数。



现在我们就可以写出一些简单的正则表达式了。比如:

String regex = ".+\\.java";  //匹配.java为后缀名的文件
regex = "\w{5,8}"  //匹配用户名必须是5-8位字母数字下划线

数量词后面可以通过加入"+"和"?"控制正则表达式的匹配力度。默认为"Greedy"(贪婪),正则表达式会全部吃入,如果无法匹配则回溯字符,最后会返回匹配的最长子串。而加上"?"表示"Reluctant"(勉强),正则表达式只会一个个吃入,只要匹配则返回。加上"+"表示"Possessive"(独占),它与"Greedy"相似,只是不会回溯。例如:

Pattern p = Pattern.compile(".+\\.java");
Matcher m = p.matcher("Test.java.txt.java");
if (m.find()) {
    System.out.println(m.group());   //Test.java.txt.java
}

Pattern p = Pattern.compile(".+?\\.java");
Matcher m = p.matcher("Test.java.txt.java");
if (m.find()) {
    System.out.println(m.group());   //Test.java
}
正则表达式中还提供了"^"和"$"两个操作符用于对应开头和结尾,"^"紧跟的字符必须是开头而"$"的前一个字符必须是结尾。这在许多情况下可以提高匹配的正确性,例如我们上边的后缀名表达式:

String regex = ".+\\.java";  //如果文件命名为Test.java.txt也会错误的被当成java文件
regex =  "^.+\\.java$"  //这样可以保证文件名一定以.java结尾
除了上面这些经常用到的符号,正则中还有一些例如特殊构造(非捕获)等写法,由于比较少用本文便不多加说明了,感兴趣的朋友可以去自行查询。




郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。