用于模式匹配,例如查询串中的数字、验证邮箱是否符合要求等。
在java中主要实现类有Pattern类、Matcher类。
Pattern类没有公共构造方法由静态方法Pattern.compile()构建,主要用于构造正则表达式并创建Matcher类。
Matcher类是对输入字符串进行解释和匹配的引擎。
//创建Pattern对象
Pattern compile = Pattern.compile("^((http|https)://)?[\\w_.]+[/\\w?=&_]+");
String s ="https://www.bilibili.com/video/BV1fh411y7R8?p=894&spm_id_from=pageDriver&vd_source=0a45c187143501cf39e6c09100236de9";
//由Pattern对象生成matcher匹配引擎
Matcher matcher = compile.matcher(s);
//循环匹配
while (matcher.find()){
System.out.println(matcher.group(0));//group是分组匹配
}
String replaceAll(String replacement); //将匹配上的字符替换成replacement,返回替换后的字符串
boolean matches(); //判断整个串是否完全被匹配
Pattern compile = Pattern.compile("(\\d)(\\d)");
String s="12ab";
Matcher matcher = compile.matcher(s);
String s2 = matcher.replaceAll("cd");
System.out.println(s2);//cdab
System.out.println(matcher.matches());//false 因为只有12被匹配上,不属于完全被匹配。
String replaceAll(String regex, String replacement)
String[] split(String regex)
boolean matches(String regex)
需要用转义符//的 .*+()$/?[]^{}
[] 接收其中的一个字符
[^abcd] 除了abcde接收一个字符
. 匹配除了\n的任意一个字符
\\d 匹配一个数字相当于[0-9]
\\D 匹配一个非数字
\\d\\d? ?表示匹配0~1个,这里是匹配1个或两个数字
\\w 匹配单个数字或大小写字母下划线
\\W 匹配单个非数字大小写字母下划线
\\d+ 匹配1个或多个数字
\\W+\\d 匹配以非数字字母开头,数字结尾的串
(?i)abc 匹配abc不区分大小写
a(?i)b 匹配ab,b不区分大小写
Pattern compile1 = Pattern.compile("abc",Pattern.CASE_INSENSITIVE); //不区分大小写
\\s 匹配空格或制表符
\\S 匹配非空白字符
ab|bc 匹配单个ab或者cd
Pattern compile = Pattern.compile("ab|bc");
String s="abbc";
最终匹配结果为:ab 、bc
* 匹配0次或多次
+ 匹配1次或多次
? 匹配0次或1次
{n} 匹配长度为n
{n,} 至少匹配长度n
{n,m}匹配长度为n到m
^ 指定起始字符 ^[0-9]abc匹配数字开头abc为尾
$ 指定结束字符 ^[0-9]\\-[a-z]+ $ 数字开头-字母结尾
\\b 匹配边界 hs\\b只能匹配右侧边界的“hs”
\\B 匹配左边界
分组匹配主要分为非命名捕获、命名捕获,顾名思义区别是分的组有没有被命名。
用括号包起来就算一组,获取结果时可以用group(i)来获取第i组的串,用group(0)获取整组的匹配结果。
Pattern compile = Pattern.compile("(\\d)(\\d)");
String s="1234";
Matcher matcher = compile.matcher(s);
while (matcher.find()){
System.out.println("整组:"+matcher.group(0));
System.out.println("第一组:"+matcher.group(1));
System.out.println("第二组:"+matcher.group(2));
}
group是什么?
这涉及到Matcher底层的一个groups数组,每次在匹配成功时groups数组会被赋值以记录匹配串的位置和各个组串的位置。groups[0-1]记录整个匹配的结果,groups[2-3]记录第一个组的结果…每次通过match.group(i)会将groups[i2~i2+1]的串拼接作为返回值返回。
public String group(int group) {
if ((groups[group*2] == -1) || (groups[group*2+1] == -1))
return null;
return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
}
在分组的括号前加入?<组名>即可为分组命名,获取分组时可按照分组名来获取。
Pattern compile = Pattern.compile("(?\\d)(?\\d)" );//分g1,g2组两组
String s ="12345678";
Matcher matcher = compile.matcher(s);
while (matcher.find()){
System.out.println("g1组结果:"+matcher.group("g1"));
System.out.println("g2组结果:"+matcher.group("g1"));
}
正则表达式内部可以用\\i代替第i个分组,外部可以用$i替代第i个分组
需求:用正则表达式匹配4个数字的串,要求第一个数字与最后一个数字相同,第二个数字与第三个数字相同。如1221
这样的需求该怎么做?可以用分组加上反向引用即用\1\2代替分组的子串
Pattern compile = Pattern.compile("(\\d)(\\d)\\2\\1");
需求2:去除重复的数字,如112233 ->123
Pattern compile = Pattern.compile("(.)\\1+");//匹配相同的串,每次会匹配到11、22、33
String s="112233";
Matcher matcher = compile.matcher(s);
String s2 = matcher.replaceAll("$1");//匹配到11时用分组1(1)替代,匹配到22时用分组1(2)替代....
System.out.println(s2);//123
什么是贪婪匹配?正则表达式匹配会尽可能匹配长度最大的串。 在str=“111"时,用正则表达式”\d+"去匹配则会得到111。非贪婪匹配则会分3次得到1,1,1
Pattern compile = Pattern.compile(“\d+?”);
在匹配的后面加个?每次可尽可能少的匹配。
1.判断输入是否全为汉字汉字
Pattern compile = Pattern.compile("^[\\u0391-\\uffe5]+$");
2.验证邮政编码 (是1-9开头的6位数 如:12306)
Pattern compile = Pattern.compile("^[1-9]\\d{5}$");
3.验证QQ号1-9开头的5~10位数
Pattern compile = Pattern.compile("^[1-9]\\d{4,9}$");
4.手机号(必须以13,14,15开头的11位数)
Pattern compile = Pattern.compile("^1[3|4|5|8]\\d{9}$");