Java正则表达式
如何匹配字符串?
如何判断字符串是否是有效的电话号码?
如何判断字符串是否是有效的电子邮件地址?
如何判断字符串是有效的时间?
从网页上爬取数据后如何判断哪些是图片资源?
那我们就开始学习正则表达式吧!
正则表达式可以用字符串来描述规则,并用来匹配字符串
- 一个正则表达式就是一个描述规则的字符串
- 只需要编写正确的规则,就可以让正则表达式引擎去判断目标字符串是否符合规则
- 正则表达式是一套标准,可以用于任何语言
- JDK内置正则表达式引擎:java.util.regex
我们来举个例子:判断用户输入的年份是否是19xx年
首先用户输入的规则是:
然后我们就可以编写出相应的正则表达式:1 9 \d \d (\d表示0-9的任意一个数字)
所有对应的Java字符串: "19\\d\\d" (java中\是转移字符所有我们要用两个反斜杠来表示一个反斜杠)
Java代码:
String input = "1996";
boolean matches = input.matches("19\\d\\d");
if (matches){
System.out.println("输入格式正确");
}else {
System.out.println("输入格式错误");
}
正则表达式的匹配规则
- 从左到右按规则匹配
如何编写正则表达式?
1、精确匹配:"abc"
表示精确的匹配"abc"这个字符串,并且大小写敏感,不能匹配"Abc"
String input = "abcd";
boolean matches = input.matches("abc");
if (matches){
System.out.println("输入格式正确");
}else {
System.out.println("输入格式错误");
}
//输入格式错误
//如果 String input = "abc"; 则输入格式正确
2、精确匹配:"a\&c",特殊字符需要转义
3、特殊符号 . 可以匹配一个任意字符 : "a.c"
String input = "a和c";
boolean matches = input.matches("a.c");
if (matches){
System.out.println("输入格式正确");
}else {
System.out.println("输入格式错误");
}
}
//格式正确
//”ac“ 和 "abbc" 是不会匹配成功的
4、符号\d可以匹配一个数字:"00\d"
String input = "009";
boolean matches = input.matches("00\\d");
//"009" 匹配成功
//"00A"和"0088"是不会匹配成功的
5、符号\w可以匹配一个字母、数字或下划线: "java\w"
String input = "java_";
boolean matches = input.matches("java\\w");
//"java_" 匹配成功
//"java#" 和 "java "是不会匹配成功的
6、符号\s可以匹配一个空白字符 : "A\sB"
String input = "A B";
boolean matches = input.matches("A\\sB");
// B"匹配成功
// B" 可以匹配成功 tab键也算空白字符
//B" 和 "A B" 不行
7、符号\D可以匹配一个非数字: "00\D"
String input = "00A";
boolean matches = input.matches("00\\D");
//"00A" 匹配成功
//"001" 和 "004" 不行
8、符号\W可以匹配一个非字母、数字或下划线: "java\W"
String input = "java!";
boolean matches = input.matches("java\\W");
//"java!" 匹配成功
//"java2" 、 "Javaa" 和 "java_" 不行
9、符号\S可以匹配一个非空白字符
String input = "ABB";
boolean matches = input.matches("A\\SB");
//"A&B" 也可以成功
//"A B" 和 "A B" 不行 tab键也算空白键
10、修饰符*可以匹配任意个字符: "A\d*"
String input = "A4674";
boolean matches = input.matches("A\\d*");
// "A" , "A1" 和 "A876" 都可以
// "AH" 不行
11、修饰符+可以匹配至少一个字符:"A\d+"
String input = "A4674";
boolean matches = input.matches("A\\d+");
//"A4674"
//"A" 、 "AV" 不可以
12、修饰符?可以匹配零个或者一个字符: "A\d?"
String input = "A4";
boolean matches = input.matches("A\\d?");
// "A" "A1" 可以
// "A12" "Ab" 不可以
13、修饰符{n}可以匹配n个字符: "\d{6}"
String input = "345325";
boolean matches = input.matches("\\d{6}");
//"123456" "111111" 可以
//"1234" "12345a" 不行
14、修饰符{n,m}可以匹配n-m个字符:"\d{3,5}"
String input = "34532";
boolean matches = input.matches("\\d{3,5}");
//"123" "12345" 可以
//"123456" "1234A" 不行
15、修饰符{n,}可以匹配至少n个字符:"\d{3,}"
String input = "123";
boolean matches = input.matches("\\d{3,}");
//"123" "12345" "1234567" 可以
//"12" "12A" 不行
我们给简单匹配规则做个小总结
正则表达式 | 规则 | 可以匹配 |
---|---|---|
A | 指定字符 | A |
. | 任意字符 | a,c,d,&,4 |
\d | 0-9 | 0,1,2,3.....9 |
\w | a-z,A-Z,1-9,_ | a,A,2,_...... |
\s | 空格,Tab键 | " " |
\D | 非数字 | a,A,&,_...... |
\W | 非\w | &^%$... |
\S | 非\s | a,A,%,_ |
我们再来看看复杂一点的匹配规则
1、和$匹配开始和结尾:"A\d{3}$"
String input = "A001";
boolean matches = input.matches("^A\\d{3}$");
//"A001" "A777" 可以
//"B001" "B0001" 不行
2、[...]可以匹配范围内的字符:"[abc]1" 只能匹配某一个字符
String input = "A001";
boolean matches = input.matches("[abc]1");
//"a1" "b1" "c1" 可以
//"ab1" "x1" 不行
3、[...] 可以匹配范围内的字符:"[a-f]1"
String input = "d1";
boolean matches = input.matches("[a-f]1");
//"a1" "b1" "f1"可以
//"r1" "ab1" 不行
4、[...] 可以匹配范围内的字符:"[a-f0-9]{6}}"
String input = "433abc";
boolean matches = input.matches("[a-f0-9]{6}");
//"1a2b4c" "ffffff" "111111" 可以
//"agc2" "ad222F" 不行 F大写不在a-f范围内
//还可以写成 boolean matches = input.matches("[a-f0-9_]{6}");
//那就还可以匹配_
5、[^] 可以匹配非范围内的字符:"[ ^ 0-9]"
String input = "asdfgh";
boolean matches = input.matches("[^0-9]{6}");
//"asdfgh" "$$$$$$" "a-b-c" 可以
//"123456" "ads23f" 不可以
6、AB|CD 可以匹配AB或CD : "java|go"
String input = "java";
boolean matches = input.matches("java|go");
//"java" "go" 可以
//"c++" "javago" 不行
//再举个例子
boolean matches = input.matches("love\\s(java|go)");
//"love java" "love go" 可以
//"love c++" "love python" 不可以
我们来做个小总结
正则表达式 | 规则 | 可以匹配 |
---|---|---|
^ | 开头 | 字符串开头 |
$ | 结尾 | 字符串结尾 |
[ABC] | [...]内任意字符 | A,B,C |
[a-f0-9xy] | 指定范围的字符 | a,2,x,y |
[^A-F] | 指定范围外的任意字符 | 非A....F |
AB|CD | AB或CD | AB,CD |
AB|CD|EF | AB或CD或EF | AB,CD,EF |
再来说一说分组匹配规则
1、(...)可以分组:(\d{4}\-\d{1,2}\-(\d{1,2}))
String input = "2020-11-22";
boolean matches = input.matches("(\\d{4}\\-(\\d{1,2})\\-(\\d{1,2}))");
//"2020-11-22" 可以
我们再来举个例子,提取电话号码
-########
^ \d{3,4} \- \d{6,8} $
^ :开头
\d{3,4}:3-4位区号
\- : 符号"-"
\d{6,8}:6-8位电话号码
$ 结束
String input = "010-1234567";
boolean matches = input.matches("^(\\d{3,4})\\-(\\d{6,8})$");
//"010-1234567"可以
反复使用一个正则表达式字符串进行快速匹配效率较低(方法内部实际上是调用了Pattern对象)
我们可以把正则表达式编译为Pattern对象,然后反复使用他,就可以实现一次编译多次匹配
Pattern pattern = Pattern.compile("^(\\d{3,4})\\-(\\d{6,8})$");
boolean matches = pattern.matcher("010-1234567").matches();
if (matches){
System.out.println("输入格式正确");
}else {
System.out.println("输入格式错误");
}
**使用Matcher.group(n)可以快速提取子串 ** 一个()代表一个子串
Pattern pattern = Pattern.compile("^(\\d{3,4})\\-(\\d{6,8})$");
Matcher matcher = pattern.matcher("010-1234567");
if (matcher.matches()){
String whole = matcher.group(0); //"010-1234567" 0表示匹配整个字符串
String areaCode = matcher.group(1); //"010" ,1表示匹配第一个字符串
String telNumber = matcher.group(2); //"1234567",表示匹配的第二个字符串
}
非贪婪匹配
正则表达式默认使用贪婪匹配
- 尽可能多的向后匹配
- 使用?实现非贪婪匹配
搜索和替换
使用正则表达式分割字符串
-
String[] String.split(String regex)
String[] split = "a b c".split("\\s");//["a", "b", "c"] String[] split = "a b c".split("\\s");//["a", "b","", "c"] String[] split = "a b c".split("\\s+");//["a", "b","c"] String[] split = "a, b;; c".split("\\,\\;\\s+");//["a", "b","c"]
使用正则表达式搜索字符串
- Matcher.find()
String str = "I love you";
Pattern pattern = Pattern.compile("love");
Matcher matcher = pattern.matcher(str);
while (matcher.find()){
String substring = str.substring(matcher.start(), matcher.end());
System.out.println(substring);
}
使用正则表达式替换字符串
-
String.replaceAll()
String str = "I love you"; String all = str.replaceAll("\\s+", ""); //Iloveyou