1. Pattern类和Matcher类
如果要在程序中应用正则表达式则必须依靠Pattern类和Matcher类,这两个类都在java.util.regex包中定义。Pattern类的主要作用是进行正则规范,而Matcher类主要是执行规范,验证一个字符串是否符合其规范。
常用的正则规范如表1~3所示:
表1 常用的正则规范
表2 数量表示(X表示一组规范)
表3 逻辑运算符(X、Y表示一组规范)
在Pattern类中直接使用表1~3中的正则规则即可完成相应的操作,Pattern类的常用方法如表4所示:
表4 Pattern类的常用方法
表5 Matcher类常用的方法:
下面直接使用Pattern类和Matcher类完成一个简单的验证过程。
日期格式要求:yyyy-mm-dd
正则表达式如下所示:
日期 : 2018 - 07 - 15
格式 : 四位数字 - 两位数字 - 两位数字
正则 : \d{4} - \d{2} - \d{2}
简单匹配:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexDemo1 {
public static void main(String[] args) {
String str = "2018-07-15";
String pat = "\\d{4}-\\d{2}-\\d{2}"; //定义验证规则
Pattern pattern = Pattern.compile(pat); //实例化Pattern类
Matcher m = pattern.matcher(str); //使用正则验证
if (m.matches()) {
System.out.println("日期格式合法");
}
else {
System.out.println("日期格式不合法");
}
}
}
输出结果为:
日期格式合法
在程序中’\’字符需要进行转义的,两个‘\’实际上表示一个‘\’,所以‘\\d’表示的是’\d’。
字符串拆分:
Pattern类也可以对一个字符串进行拆分操作:
import java.util.regex.Pattern;
public class RegexDemo2 {
public static void main(String[] args) {
String str = "A1B22C33D4444E55555F";
String pat = "\\d+";
Pattern pattern = Pattern.compile(pat);
String[] s = pattern.split(str);
for (int i = 0; i < s.length; i++) {
System.out.print(s[i] + "\t");
}
}
}
输出结果为:
A B C D E F
字符串替换
了解了匹配和拆分操作,下面再来看Matcher类中的替换操作,如:将全部数字替换成“_”:
mport java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexDemo3 {
public static void main(String[] args) {
String str = "A1B22C33D4444E55555F";
String pat = "\\d+";
Pattern pattern = Pattern.compile(pat);
Matcher matcher = pattern.matcher(str);
String newString = matcher.replaceAll("_");
System.out.println(newString);
}
}
输出结果:
A_B_C_D_E_F
macher类还有几个重要的方法:
boolean find()
如果存在匹配的子序列,就返回true,否则返回false。可以重复调用这个方法,以查找所有匹配的子序列。对find()的每次调用,都是从上一次离开的位置开始。
String group()
可以通过group()方法来获得包含最后一个匹配序列的字符串。该方法返回匹配的字符串。如果不匹配,就抛出IllegalStateException异常。
下面通过几个简单例子演示group()函数用法:
第一个例子通过使用量词‘+’来匹配任意长度的“W”序列
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexDemo4 {
public static void main(String[] args) {
Pattern pat = Pattern.compile("W+");
Matcher mat = pat.matcher("W WW WWW");
while (mat.find()) {
System.out.println("Match: " + mat.group());
}
}
}
输出:
Match: W
Match: WW
Match: WWW
正则表达式的贪婪匹配
第二个例子使用通配符创建一个模式,该模式将匹配以e开始并以d结束的任意序列,为了达到这个目的,使用点通配符和‘+’量词,同时我们还要介绍一下贪婪匹配:
public class RegexDemo5 {
public static void main(String[] args) {
Pattern pat = Pattern.compile("e.+d");
Matcher mat = pat.matcher("extend cup end table");
while (mat.find()) {
System.out.println("Match: " + mat.group());
}
}
}
输出结果:
Match: extend cup end
从输出结果看出,程序最终只发现一个匹配,即以e开头并以d结尾的最长序列。你可能疑惑为什么不是两个匹配:“extend”和“end”。这是由于,在默认情况下,find()方法会匹配适合模式的最长序列,这被称为贪婪行为(greedy behavior),可以通过为模式添加“?”量词来指定懒惰行为(reluctant behavior),如下面一个例子所示,这将导致获得最短的匹配模式:
正则表达式的懒惰匹配
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexDemo7 {
public static void main(String[] args) {
Pattern pat = Pattern.compile("e.+?d");
Matcher mat = pat.matcher("extend cup end table");
while (mat.find()) {
System.out.println("Match: " + mat.group());
}
}
}
输出结果:
Match: extend
Match: end
int start()
通过调用start()方法,获得输入序列的当前匹配索引。
int end()
通过调用end()方法,可以获得当前匹配序列末尾之后下一个字符的索引。
下面这个例子演示了find()、start()和end()的用法:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexDemo8 {
public static void main(String[] args) {
Pattern pat = Pattern.compile("test");
Matcher mat = pat.matcher("test 1 2 3 test");
while (mat.find()) {
System.out.println("test found at index " + mat.start() + " and end at index " + mat.end());
}
}
}
输出结果:
test found at index 0 and end at index 4
test found at index 11 and end at index 15