匹配规则
正则表达式的匹配规则就是从左到右按规则匹配
匹配任意字符
// 在正则表达式中,'.'表示匹配任意一个字符
public class Regex{
public static void main(String[] argc){
String s = "cde";
boolean f = s.matches("c.e");
System.out.println(f); //true
}
}
匹配数字
// 在正则表达式中,'d'可以匹配单个数字字符
// 因为正则在java中也是作为字符串,所以使用时要用'\d',需要对进行转义
public class Regex{
public static void main(String[] argc){
String s = "cde8";
boolean f = s.matches("c.e\d");
System.out.println(f); //true
}
}
匹配常用字符
// 在正则表达式中,'w'可以匹配一个字母、数字或者下划线,w(word),除此之外不能匹配任何字符,像#、空格……
public class Regex{
public static void main(String[] argc){
String s = "cde8";
boolean f = s.matches("c\we\w");
System.out.println(f); //true
}
}
匹配空格字符
// 在正则表达式中,'s'可以匹配一个空格字符,包括tab(t)
public class Regex{
public static void main(String[] argc){
String s = "c de 8";
boolean f = s.matches("c\s\we\s\d");
System.out.println(f); //true
}
}
匹配非数字
// 'd'可以匹配一个数字,'D'则匹配一个非数字 // 相应的 'W' 可以匹配 'w' 不能匹配的字符 // 'S' 可以匹配 's' 不能匹配的字符
重复匹配
// 修饰符 * 可以匹配任意个字符,包括0个
// 'Ad*' 可以匹配 'A' 'A0' 'A380'
// 修饰符 + 可以匹配至少一个字符
// 'Ad+' 可以匹配 'A0' 'A380'
// 修饰符 ? 可以匹配0个或者1个字符
// 'Ad?' 可以匹配 'A' 'A0'
//如果想精确指定n个字符,使用修饰符{n}
//例如 'd{3}'可以匹配三个数字
// 使用{n,m}可以制定匹配n~m个字符,没有上限,使用{n,}
案例:使用正则匹配国内电话号码规则:34位区号加78位电话,中间用 - 连接
import java.util.Scanner;
public class Regex{
public static void main(String[] argc){
Scanner scan = new Scanner(System.in);
String s = scan.next();
scan.close();
System.out.println(s.matches("\d{3,4}-\d{7,8}"));
}
}
复杂匹配规则
匹配开头和结尾
// 使用正则表达式进行多行匹配时,使用 ^ 表示开头,使用 $ 表示结尾
// 例如 '^Ad{3}$' 表示以A开头,以三个数字结尾
匹配指定范围
// 正则表达式使用 [] 进行范围匹配
// 例如 '[1-9]d{6,7}'
// 要匹配大小写不限的十六进制数,比如 1A2b3c 使用[0-9a-fA-F]
// 如果要匹配 6 位十六进制数,则[0-9a-fA-F]{6}即可
进阶案例:电话号码匹配规则中区号以0开头,号码不能以0开头
import java.util.Scanner;
public class Regex{
public static void main(String[] argc){
Scanner scan = new Scanner(System.in);
String s = scan.next();
scan.close();
System.out.println(s.matches("^0\d{2,3}-[1-9]\d{6,7}"));
}
}
或规则匹配
// 使用 | 连接两个正则规则 例如AB|CD 匹配AB或者CD // 当匹配多个字符串,且字符串具有公共部分时,可以提取公共部分,使用小括号括起来非公共部分 // learns(java|php|go) 有点类似分配率
分组匹配
使用 (…) 进行分组
// 例如 (d{3,4})-(d{6,8})
提取字符串
import java.util.Scanner;
import java.util.regex.*;
public class Regex{
public static void main(String[] argc){
Scanner scan = new Scanner(System.in);
String s = scan.next();
scan.close();
Pattern p = Pattern.compile("(^0\d{2,3})-([1-9]\d{6,7})");
Matcher m = p.matcher(s);
if(m.matches()){
String g1 = m.group(1);
String g2 = m.group(2);
System.out.print(g1 + " " + g2);
}else{
System.out.print("匹配失败");
}
}
}
//输入:010-1000000
//输出:010 1000000
注:Matcher.group(index) 参数 1 表示第一个字符串, 2 表示第二个字符串,0表示原来的字符串
使用Pattern
//前面用到的String.matches(String regex)内部调用的还是Pattern 和
//Matcher类中的方法,当需要多次进行匹配时,每次都会创建不同的Pattern
//对象,因此效率较低,因此可以创建Pattern对象,创建一次可以多次进行匹配
import java.util.Scanner;
import java.util.regex.*;
public class Regex{
public static void main(String[] argc){
Scanner scan = new Scanner(System.in);
String s = scan.next();
scan.close();
Pattern p = Pattern.compile("(^0\d{2,3})-([1-9]\d{6,7})");
Matcher m = p.matcher(s);
//可以使用Pattern的实例 p 匹配更多地字符串
//p.matcher(String s)
if(m.matches()){
String g1 = m.group(1);
String g2 = m.group(2);
System.out.print(g1 + " " + g2);
}else{
System.out.print("匹配失败");
}
}
}
注:使用Matcher类中的方法时,必须先判断是否匹配成功,及调用Matcher.matches()方法
练习:从字符串 “23:01:59” 提取时分秒
import java.util.Scanner;
import java.util.regex.*;
public class Regex{
public static void main(String[] argc){
Scanner scan = new Scanner(System.in);
String s = scan.next();
scan.close();
Pattern pattern = Pattern.compile("([0-2][0-9]):([0-5][0-9]):([0-5][0-9])");
Matcher m = pattern.matcher(s);
if(m.matches()){
String time = m.group(0);
String hour = m.group(1);
String minute = m.group(2);
String second = m.group(3);
System.out.println("时间:" + time);
System.out.println("小时:" + Integer.parseInt(hour) + " 分钟:" + Integer.parseInt(minute) + " 秒:" + Integer.parseInt(second));
}else{
System.out.println("匹配失败");
}
}
}
//输入 :23:01:05
//时间:23:01:05
//小时:23 分钟:1 秒:5
非贪婪匹配
贪婪匹配
正则表达式默认使用贪婪匹配,即任何一个规则,它总是尽可能多的向后匹配
非贪婪匹配
在规则的后面加上 ? 即可表示非贪婪匹配
//下面的代码用来判断一串数字末尾0的个数
import java.util.regex.*;
public class Regex{
public static void main(String[] argc){
Pattern pattern = Pattern.compile("(\d+?)(0*)");
Matcher m = pattern.matcher("012000");
Matcher m1 = pattern.matcher("1200100000");
Matcher m2 = pattern.matcher("01000");
Matcher m3 = pattern.matcher("0001");
if(m1.matches() && m2.matches() && m3.matches() && m.matches()){
String g = m.group(2);
String g1 = m1.group(2);
String g2 = m2.group(2);
String g3 = m3.group(2);
System.out.println(m.group(0)+"末尾有" + g.length() + "个零");
System.out.println(m1.group(0)+"末尾有" + g1.length() + "个零");
System.out.println(m2.group(0)+"末尾有" + g2.length() + "个零");
System.out.println(m3.group(0)+"末尾有" + g3.length() + "个零");
}else{
System.out.print("匹配失败");
}
}
}
搜索和替换
字符串分割
使用 String.split(String regex);
"a, b ;; c".split("[\,\;\s]+");
搜索字符串
我们获取Matcher对象时,不需要调用matcher方法,因为对整个字符串返回肯定是false,因此需要反复调用find方法,在整个串上匹配正则
import java.util.regex.*;
public class Regex{
public static void main(String[] argc){
String s = "the quick brown fox jumps over the lazy dog";
Pattern pattern = Pattern.compile("\wo\w");
Matcher m = pattern.matcher(s);
while(m.find()){
String sub = s.substring(m.start(), m.end());
System.out.println(sub);
}
}
}
//输出:
// row
// fox
// dog
替换字符串
使用正则表达式替换字符串可以直接调用String.replaceAll(String regex, String s)
import java.util.regex.*;
public class Regex{
public static void main(String[] argc){
String s = "the tt quick brown fox jumps over the t lazy dog";
String ns = s.replaceAll("\s+", " ");
System.out.println(ns);
}
}
反向引用
即将匹配到的字符串作为引用来使用,使用$1、$2来反向引用匹配到的子串
import java.util.regex.*;
public class Regex{
public static void main(String[] argc){
String s = "the quick brown fox jumps over the lazy dog.";
String r = s.replaceAll("\s([a-z]{4})\s", " $ ");
System.out.println(r);
}
}
总结来说,正则表达式在任何编程语言中都是适用的,而且在判断一些字符串是否符合某种规范的时候特别方便,就是记忆的内容比较多,但是相对来说还是很好理解的,不需要怎么记,只需要明白每一种规则的使用即可,重点是如何灵活组合正则表达式来达到某种要求,因此需要多练习



