正则表达式是一个强大的字符串处理工具,可以对字符串进行查找、提取、分隔、替换等操作。String类里提供了如下几个特殊方法

  • boolean matches(String regex):判断该字符串是否匹配指定的正则表达式

  • String replaceAll(String regex, String replacement):将该字符串中所有匹配regex的子串替换成replacement

  • String replaceFirst(String regex, String replacement):将该字符串中第一个匹配regex的子串替换成replacement

  • String[] split(String regex):以regex为分隔符,把该字符串分割成多个子串

创建正则表达式

正则表达式是用于匹配字符串的模板,可以匹配一批字符串,所以创建正则表达式就是创建一个特殊的字符串

正则表达式所支持的合法字符

字符 解释
x 字符x
0mnn 八进制数0mnn所表达的字符
xhh 十六进制数0xhh所表达的字符
uhhhh 十六进制数0xhhhh所表达的Unicode字符
t 制表符('u0009)
n 新行(换行)符('u000A)
r 回车符('u000D)
f 换页符('u000C)
a 报警(bell)符('u0007)
e Escape符('u001B)
cx x对应的控制符。cM匹配Ctrl-M,x必须为A~Z或a~z

正则表达式中的特殊字符

clipboard.png

预定义字符

正则表达式中的“通配符”远远超出了普通通配符的功能,被称为预定义字符。
clipboard.png

方括号表达式

clipboard.png

圆括号表达式

用于将多个表达式组成一个子表达式,圆括号中可以使用或运算符(|)。例如,正则表达式"((public)|(protected)|(prvate))"用于匹配Java的三个访问控制符其中之一

边界匹配符

clipboard.png

数量标识符

  • Greedy(贪婪模式):数量表示符默认采用贪婪模式。贪婪模式的表达式会一直匹配下去,直到无法匹配

  • Reluctant(勉强模式):用问号后缀(?)表示,只会匹配最少的字符,也称为最小匹配模式

  • Possessive(占有模式):用加号后缀(+)表示,目前只有Java支持占有模式,通常较少使用

clipboard.png

贪婪模式和勉强模式的对比:

String str = "SSR! 大天狗";
//贪婪模式的正则表达式
System.out.println(str.replaceFirst("\\w*","□"));
//勉强模式的正则表达式
System.out.println(str.replaceFirst("\\w*?","□"));

"\w"使用了贪婪模式,数量表示符()会一直匹配下去,所以该字符串前面的所有单词 字符都被它匹配到,直到遇到空格,所以替换后的效果是“□! 大天狗”;如果使用勉强模式,数量表示符(*)会尽量匹配最少字符,即匹配0个字符,所以替换后的结果是“□SSR! 大天狗”。

使用正则表达式

Pattern对象是正则表达式编译后在内存中的表示形式,因此,正则表达式字符串必须先被编译为Pattern对象,然后再利用该Pattern对象创建对应的Matcher对象。执行匹配所涉及的状态保留在Matcher对象中,多个Matcher对象可共享同一个Pattern对象。

典型调用顺序

//将一个字符串编译成Pattern对象
Pattern pattern = Pattern.compile("a*b");
//使用Pattern对象创建Matcher对象
Matcher matcher = pattern.matcher("aaaaab");
boolean b = matcher.matches();        //返回true

上面定义的Pattern对象可以多次重复使用。如果仅需一次使用,则可直接使用Pattern类的静态matches()方法,此方法自动把指定字符串编译成匿名的Pattern对象,并执行匹配

boolean b = pattern.matches("a*b", "aaaaab");        //返回true

上面语句等效于前面的三条语句,但采用这种语句每次都需要重新编译新的Pattern对象,不能重新利用已编译的Pattern对象,所以效率不高

Pattern是不可变类,可供多个并发线程安全使用

Matcher类提供的常用方法:

  • find():返回目标字符串中是否包含与Pattern匹配的子串

  • group():返回上一次与Pattern匹配的子串

  • start():返回上一次与Pattern匹配的子串在目标字符串中的开始位置

  • end():返回上一次与Pattern匹配的子串在目标字符串中结束位置加1

  • lookingAt():返回目标字符串前面部分与Pattern是否匹配

  • matches():返回整个目标字符串与Pattern是否匹配

  • reset():将现有的Matcher对象应用于一个新的字符序列

CharSequence接口,该接口代表一个字符序列,其中CharBuffer、String、StringBuffer、StringBuilder都是它的实现类。

通过Matcher()类的find()和group()方法从目标字符串中依次取出特定子串(匹配正则表达式的子串)

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class FindGroup 
{
    public static void main(String[] args) 
    {
        //使用字符串模拟从网络上得到的网页源码
        String string = "四洲休闲食品:0754-88117038" + 
        "清风牌面巾纸:8008282272" + "统一冰红茶:4007000660";
        //创建一个Pattern对象,并用它建立一个Matcher对象
        //该正则表达式只抓取400X和800X段的电话号码
        //实际要抓取哪些电话号码,只要修改正则表达式即可
        Matcher matcher = Pattern.compile("((400\\d)|(800\\d))\\d{6}").matcher(string);
        //将所有符合正则表达式的子串(电话号码)全部输出
        while (matcher.find()) 
        {
            System.out.println(matcher.group());
        }
    }
}

find()方法还可以传入一个int类型的参数,带int参数的find()方法将从该int索引处向下搜索。start()和end()方法主要用于确定子串在目标字符串中的位置

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StartEnd 
{
    public static void main(String[] args) 
    {
        //创建一个Pattern对象,并用它建立一个Matcher对象
        String regStr = "France LoireAtlantique Bretagne Nantes";
        System.out.println("目标字符串是:" + regStr);
        Matcher matcher = Pattern.compile("\\w+").matcher(regStr);
        while (matcher.find()) 
        {
            System.out.println(matcher.group() + 
                    "子串的起始位置:" + matcher.start() +
                    ",其结束位置:" + matcher.end());
        }
    }
}
目标字符串是:France LoireAtlantique Bretagne Nantes
France子串的起始位置:0,其结束位置:6
LoireAtlantique子串的起始位置:7,其结束位置:22
Bretagne子串的起始位置:23,其结束位置:31
Nantes子串的起始位置:32,其结束位置:38

程序创建一个邮件地址Pattern,再将其与多个邮寄地址进行匹配。当程序中的Matcher为null时,程序调用matcher()方法来创建一个Matcher对象,一旦Matcher对象被创建,程序就调用Matcher的reset()方法将该Matcher应用于新的字符序列

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MatchesTest 
{
    public static void main(String[] args) 
    {
        String[] mails =
            {
                    "LeBornJames@gmail.com",
                    "FlashWade@163.com",
                    "Bosh@yahoo.com"
            };
        String mailRegEx = "\\w{3,20}@\\w+\\.(com|org|cn|net|gov|ed)";
        Pattern mailPattern = Pattern.compile(mailRegEx);
        Matcher matcher = null;
        for (String mail : mails) 
        {
            if (matcher == null) 
            {
                matcher = mailPattern.matcher(mail);
            }
            else 
            {
                matcher.reset();
            }
            String result = mail + (matcher.matches() ? "是":"不是") + "一个有效邮件地址";
            System.out.println(result);
        }
    }
}

Matcher类提供的replaceAll()把字符串中所有与正则表达式的子串替换成:"呵呵"。还提供replaceFirst(),该方法只替换第一匹配的子串。split()方法以空格为分隔符,将字符串分割成多个子串

public class StringReg
{
    public static void main(String[] args)
    {
        String[] msgs =
        {
            "Java has regular expressions in 1.4",
            "regular expressions now expressing in Java",
            "Java represses oracular expressions"
        };
        for (String msg : msgs)
        {
        System.out.println(msg.replaceFirst("re\\w*" , "哈哈:)"));
        System.out.println(Arrays.toString(msg.split(" ")));
        }
    }
}

布still
461 声望32 粉丝

数据挖掘、用户行为研究、用户画像