正则表达式
正则表达式可以用字符串来描述规则,并用来匹配字符串,使用正则表达式可以快速判断给定的字符串是否符合匹配规则。正则表达式是一套标准,可以用于任何语言。
Java标准库的java.util.regex包内置了正则表达式引擎
匹配规则
正则表达式的匹配规则是从左到右按规则匹配。
对于正则表达式abc来说,它只能精确地匹配字符串"abc",不能匹配"ab",“Abc”,“abcd"等其他任何字符串。
如果正则表达式有特殊字符,就需要用\转义
正则表达式在Java代码中也是一个字符串,正则表达式a&c对应的Java字符串是"a\&c”
匹配的类型决定:
- 匹配任意字符:用.匹配一个任意字符
- 匹配数字:用\d匹配,仅限单个数字字符
- 匹配常用字符:用\w可以匹配一个字母、数字或下划线,w的意思是word
- 匹配空格字符:用\s可以匹配一个空格字符,注意空格字符不但包括空格,还包括tab字符(在Java中用\t表示)
- 匹配非某类型的字符:\D则匹配一个非数字,\W可以匹配\w不能匹配的字符,\S可以匹配\s不能匹配的字符
匹配的数量决定:
- 修饰符*可以匹配任意个字符,包括0个字符
- 修饰符+可以匹配至少一个字符
- 修饰符?可以匹配0个或一个字符
- 修饰符{n}可以精确指定n个字符
- 修饰符{n,m}可以指定匹配n~m个字符,如果没有上限,修饰符{n,}可以匹配至少n个字符
单个字符的匹配规则
正则表达式 | 规则 | 可匹配的 |
---|---|---|
A | 指定字符 | A |
\u548c | 指定Unicode字符 | 和 |
. | 任意字符 | a,b,&,0 |
\d | 数字0~9 | 0~9 |
\w | 大小写字母,数字和下划线 | a ~ z,A ~ Z,0~9,_ |
\s | 空格、Tab键 | 空格,Tab |
\D | 非数字 | a,A,&,_,…… |
\W | 非\w | &,@,中,…… |
\S | 非\s | a,A,&,_,…… |
多个字符的匹配规则
正则表达式 | 规则 | 可匹配的 |
---|---|---|
A* | 任意个数字符 | 空,A,AA,AAA,…… |
A+ | 至少1个字符 | A,AA,AAA,…… |
A? | 0个或1个字符 | 空,A |
A{3} | 指定个数字符 | AAA |
A{2,3} | 指定范围个数字符 | AA,AAA |
A{2,} | 至少n个字符 | AA,AAA,AAAA,…… |
A{0,3} | 最多n个字符 | 空,A,AA,AAA |
复杂匹配规则
匹配开头和结尾:用^表示开头,$表示结尾
匹配指定范围:使用[…]可以匹配范围内的字符,不包含指定范围的字符用^,例如:
- [123456789]或[1-9]:匹配1~9
- [0-9a-fA-F]:匹配大小写不限的十六进制数
- [^1-9]{3}:匹配任意字符,但不包括数字的3个字符
或规则匹配:用|连接,AB|CD表示可以匹配AB或CD
分组匹配
用(…)把要提取的规则分组,引入java.util.regex包,用Pattern对象匹配,匹配后获得一个Matcher对象,如果匹配成功,直接从Matcher.group(index)返回子串:Matcher.group(index)方法的参数用1表示第一个子串,2表示第二个子串,0表示整个正则匹配到的字符串
使用Matcher时,须首先调用matches()判断是否匹配成功,匹配成功后,才能调用group()提取子串
import java.util.regex.*;
public class Main {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("(\\d{3,4})\\-(\\d{7,8})");
pattern.matcher("010-12345678").matches(); // true
pattern.matcher("021-123456").matches(); // true
pattern.matcher("022#1234567").matches(); // false
// 获得Matcher对象:
Matcher matcher = pattern.matcher("010-12345678");
if (matcher.matches()) {
String whole = matcher.group(0); // "010-12345678", 0表示匹配的整个字符串
String area = matcher.group(1); // "010", 1表示匹配的第1个子串
String tel = matcher.group(2); // "12345678", 2表示匹配的第2个子串
System.out.println(area);
System.out.println(tel);
}
}
}
非贪婪匹配
正则表达式默认使用贪婪匹配:任何一个规则,它总是尽可能多地向后匹配,在规则后面加个?即可表示非贪婪匹配,会尽可能少的匹配
区分?的含义:\d??
正则表达式(\d??)(9*),其中\d?表示匹配0个或1个数字,后面第二个?表示非贪婪匹配,因此,给定字符串"9999",匹配到的两个子串分别是"“和"9999”,因为对于\d?来说,可以匹配1个9,也可以匹配0个9,但是因为后面的?表示非贪婪匹配,它就会尽可能少的匹配,结果是匹配了0个9
搜索和替换
通过find方法,能够匹配符合正则表达式的字符串
使用正则表达式替换字符串可以调用String.replaceAll(),第一个参数是正则表达式,第二个参数是待替换的字符串。
public class Main {
public static void main(String[] args) {
String s = "The quick\t\t brown fox jumps over the lazy dog.";
String r = s.replaceAll("\\s+", " ");
System.out.println(r); // "The quick brown fox jumps over the lazy dog."
}
}
反向引用:要把搜索到的指定字符串按规则替换,比如前后各加一个xxxx,可使用replaceAll()传入的第二个参数可以使用$1、$2来反向引用匹配到的子串。例如:
public class Main {
public static void main(String[] args) {
String s = "the quick brown fox jumps over the lazy dog.";
String r = s.replaceAll("\\s([a-z]{4})\\s", " <b>$1</b> ");
System.out.println(r);//the quick brown fox jumps <b>over</b> the <b>lazy</b> dog.
}
}