1、概念
正则表达式(Regular Expression)是一种强大的文本处理工具,可以用来匹配、查找、替换等操作。
引出例子:校验qq号码是否正确 (qq号码不能为空,首个号码不能为0,qq长度 不能<6或 >20)
不使用正则表达式:
public static boolean checkQQ(String qq) {
if (qq == null || qq.startsWith("0") || qq.length() < 6 || qq.length() > 20) {
return false;
}
for (int i = 0; i < qq.length(); i++) {
char ch = qq.charAt(i);
if (!(ch >= '0' && ch <= '9')) {
return false;
}
}
return true;
}
使用正则表达式:
public static boolean checkQQregular(String qq) {
return qq != null && qq.matches("[1-9]\\d{5,19}");
}
可以发现使用正则表达式代码非常简洁。
String提供了一个匹配正则表达式的方法:
//判断字符串是否匹配正则表达式,匹配返回true,不匹配返回false。
public boolean matches(String regex){};
2、普通字符和元字符
普通字符
普通字符是指那些没有特殊含义的字符,它们在正则表达式中代表自己本身。例如:
a
:匹配字母a
。5
:匹配数字5
。.
:匹配点号.
(注意,.
作为元字符有特殊的含义,但在某些情况下也可以用作普通符)。
元字符
元字符元字符是具有特殊含义的字符,在正则表达式中通常用来表示某种模式或者控制匹配的行为。以下是常见的元字符及其用途:
-
锚定符
^
:匹配字符串的开始位置。$
:匹配字符串的结束位置。
-
重复符
*
:匹配前面的子表达式零次或多次。+
:匹配前面的子表达式一次或多次。?
:匹配前面的子表达式零次或一次。{m,n}
:匹配前面的子表达式至少 m 次,但不超过 n 次。
-
选择符
|
:表示逻辑“或”,用于选择多个可能的匹配之一。
-
字符类
[]
:定义一个字符集合,其中的任何一个字符都可以匹配。[^]
或[!]
:定义一个否定的字符集合,即匹配不在集合内的任何字符。
-
预定义字符类
\d
:匹配任何数字,等同于[0-9]
。\D
:匹配任何非数字,等同于[^0-9]
。\w
:匹配任何字母数字字符,包括下划线,等同于[a-zA-Z0-9_]
。\W
:匹配任何非字母数字字符,包括非下划线,等同于[^a-zA-Z0-9_]
。\s
:匹配任何空白字符,包括空格、制表符、换页符等。\S
:匹配任何非空白字符。
-
量词限定符
{n}
:匹配前面的子表达式恰好 n 次。{n,}
:匹配前面的子表达式至少 n 次。{,m}
:匹配前面的子表达式最多 m 次。{n,m}
:匹配前面的子表达式至少 n 次,但不超过 m 次。
-
特殊符号
\b
:匹配一个单词边界,即单词和非单词字符之间的位置。\B
:匹配一个非单词边界,即两个单词字符之间或两个非单词字符之间的位置。
-
转义符
\
:用于转义上述元字符或特殊字符,使其失去特殊含义,变成普通字符。例如,\.
,\+
,\\
等。
-
分组与引用
()
:用于定义一个捕获组。\1
,\2
, … :引用之前捕获组的内容。
3、案例
案例1:
校验用户输入的电话,邮箱,时间是否合法
校验电话:
手机号码:13812345678
固定电话号码:021-12345678
或 0755123456789
public static void checkPhone() {
while (true) {
System.out.println("输入手机号码");
Scanner sc = new Scanner(System.in);
String phoneNumber = sc.nextLine();
if (phoneNumber.matches("(1[3-9]\\d{9})|(0\\d(2,7)-?[1-9]\\d{4,19})")) {
System.out.println("输入正确");
} else {
System.out.println("输入错误");
}
}
}
对上述正则表达式的解释:
-
手机号码部分
1[3-9]\\d{9}
:1
: 匹配数字1
,这是中国手机号码的前缀。[3-9]
: 匹配数字 3 到 9 中的一个,这是手机号码第二位的常见值。\\d{9}
: 匹配接下来的 9 位数字,其中\d
表示任何数字 (0-9)。
-
固定电话号码或地区代码部分
0\\d(2,7)-?[1-9]\\d{4,19}
:0
: 匹配数字0
,这是中国固定电话号码的前缀。\\d
: 匹配一个数字。(2,7)
: 匹配数字 2 或 7。-?
: 可选的短横线-
,表示该短横线可能出现也可能不出现。[1-9]
: 匹配数字 1 到 9 中的一个,这确保了接下来的数字不是以 0 开始。\\d{4,19}
: 匹配接下来的 4 到 19 位数字。
校验邮箱:
username@example.co
username123@example.org
public static void checkEmail() {
while (true) {
System.out.println("输入邮箱");
Scanner sc = new Scanner(System.in);
String email = sc.nextLine();
if(email.matches("\\w{2,}@\\w{2,20}(\\ .\\w{2,10}){1,2}")){
System.out.println("输入正确");
break;
}else {
System.out.println("输入错误");
}
}
}
对上述正则表达式的解释:
1.\\w{2,}
: 匹配至少两个字母数字字符(包括字母、数字和下划线)。
2.@
: 匹配 @
符号,这是电子邮件地址的一部分。
3.\\w{2,20}
: 匹配域名部分,至少包含两个字母数字字符,最长不超过 20 个字符。
4.(\\.\\w{2,10}){1,2}
: 匹配顶级域名(TLD)或子域的部分,可以有一个或两个这样的部分。
(4.1) \\.\\w{2,10}
: 匹配一个点 .
后跟 2 到 10 个字母数字字符。
(4.2) {1,2}
: 表示上面的模式可以出现一次或两次。
案例2:
将下述的本文中的电话,邮箱,座机号码,热线都爬取出来。
package javaeeDay01.Test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test3 {
public static void main(String[] args) {
String data = "来学习Java,\n" +
"电话:18512516758,18512508907\n" +
"或者联系邮箱:boniu@itcast.cn,\n" +
"座机电话:01036517895,010-98951256\n" +
"邮箱:bozai@itcast.cn,\n" +
"邮箱2:dlei0009@163.com,\n" +
"热线电话:400-618-9090,400-618-4000,4006184000,4006189090";
//定义爬取规则
String regex = "(1[3-9]\\d{9})|(0\\d(2,7)-?[1-9]\\d{4,19})" +
"|(\\w{2,}@\\w{2,20}(\\.\\w{2,10}){1,2})" +
"|(400-?\\d{3,7}-?\\d{3,7})";
//封装成Pattern对象
Pattern pattern = Pattern.compile(regex);
//通过pattern对象获取查找内容的匹配器对象
Matcher matcher = pattern.matcher(data);
//定义循环爬取信息
while (matcher.find()) {
String str = matcher.group(); //获取找到的内容
System.out.println(str);
}
}
}
正则表达式用于搜索替换、分割内容,需要结合String提供的如下方法完成:
方法名 | 说明 |
public String replaceAll(String regex , String newStr) | 按照正则表达式匹配的内容进行替换 |
public String[] split(String regex): | 按照正则表达式匹配的内容进行分割字符串,反回一个字符串数组。 |
非中文字符替换成”-"
//非中文字符替换成”-";
String s1 = "古力娜扎ai8888迪丽热巴999aa5566马尔扎哈fbbfsfs42425卡尔扎巴";
System.out.println(s1.replaceAll("\\w+", "-"));
简化成我喜欢编程
//简化成我喜欢编程
String s2 = "我我喜欢编编编编编编编编编编编编编编编编程程";
System.out.println(s2.replaceAll("(.)\\1+", "$1"));
//获取人名
String s3 = "古力娜扎ai8888迪丽热巴999aa5566马尔扎哈fbbfsfs42425卡尔扎巴";
String[] names = s3.split("\\w+");
System.out.println(Arrays.toString(names));