第4章 常见对象 - 正则表达式的应用
优质
小牛编辑
135浏览
2023-12-01
1. 正则表达式的应用
String 类提供的几个特殊方法
方法声明 | 功能描述 |
---|---|
matches() | 判断该字符串是否匹配指定的正则表达式 |
replaceAll() | 将该字符串所有匹配正则表达式的子串替换成指定的字符串 |
replaceFirst() | 将该字符串中第一个匹配正则表达式的子串替换成指定的字符串 |
split(String regex) | 以regex为分隔符,将该字符串分割成多个子串 |
1.1 匹配功能
public boolean matches(String regex) // 编译给定正则表达式并尝试将给定输入与其匹配。
校验邮箱
package cn.itcast_02;
import java.util.Scanner;
/*
* 校验邮箱
*
* 分析:
* A:键盘录入邮箱
* B:定义邮箱的规则
* 1517806580@qq.com
* liuyi@163.com
* linqingxia@126.com
* fengqingyang@sina.com.cn
* fqy@itcast.cn
* C:调用功能,判断即可
* D:输出结果
*/
public class RegexTest {
public static void main(String[] args) {
//键盘录入邮箱
Scanner sc = new Scanner(System.in);
System.out.println("请输入邮箱:");
String email = sc.nextLine();
//定义邮箱的规则
//String regex = "[a-zA-Z_0-9]+@[a-zA-Z_0-9]{2,6}(\\.[a-zA-Z_0-9]{2,3})+";
String regex = "\\w+@\\w{2,6}(\\.\\w{2,3})+";
//调用功能,判断即可
boolean flag = email.matches(regex);
//输出结果
System.out.println("flag:"+flag);
}
}
1.2 分割功能
public String[] split(String regex) // 根据指定的正则表达式分割字符串
代码示例:我有如下一个字符串:”91 27 46 38 50”,请写代码实现最终输出结果是:”27 38 46 50 91”
package cn.itcast_03;
import java.util.Arrays;
/*
* 我有如下一个字符串:"91 27 46 38 50"
* 请写代码实现最终输出结果是:"27 38 46 50 91"
*
* 分析:
* A:定义一个字符串
* B:把字符串进行分割,得到一个字符串数组
* C:把字符串数组变换成int数组
* D:对int数组排序
* E:把排序后的int数组在组装成一个字符串
* F:输出字符串
*/
public class RegexTest {
public static void main(String[] args) {
// 定义一个字符串
String s = "91 27 46 38 50";
// 把字符串进行分割,得到一个字符串数组
String[] strArray = s.split(" ");
// 把字符串数组变换成int数组
int[] arr = new int[strArray.length];
for (int x = 0; x < arr.length; x++) {
arr[x] = Integer.parseInt(strArray[x]);
}
// 对int数组排序
Arrays.sort(arr);
// 把排序后的int数组在组装成一个字符串
StringBuilder sb = new StringBuilder();
for (int x = 0; x < arr.length; x++) {
sb.append(arr[x]).append(" ");
}
//转化为字符串
String result = sb.toString().trim();
//输出字符串
System.out.println("result:"+result);
}
}
1.3 替换功能
public String replaceAll(String regex,String replacement)
使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
- 论坛中不能出现数字字符,用*替换
package cn.itcast_04;
/*
* 替换功能
* String类的public String replaceAll(String regex,String replacement)
* 使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
*/
public class RegexDemo {
public static void main(String[] args) {
// 定义一个字符串
String s = "helloqq12345worldkh622112345678java";
// 我要去除所有的数字,用*给替换掉
// String regex = "\\d+";
// String regex = "\\d";
//String ss = "*";
// 直接把数字干掉
String regex = "\\d+";
String ss = "";
String result = s.replaceAll(regex, ss);
System.out.println(result);
}
}
1.4 获取功能
Pattern和Matcher类的使用
package cn.itcast_05;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
* 获取功能
* Pattern和Matcher类的使用
*
* 模式和匹配器的基本使用顺序
*/
public class RegexDemo {
public static void main(String[] args) {
// 模式和匹配器的典型调用顺序
// 把正则表达式编译成模式对象
Pattern p = Pattern.compile("a*b");
// 通过模式对象得到匹配器对象,这个时候需要的是被匹配的字符串
Matcher m = p.matcher("aaaaab");
// 调用匹配器对象的功能
boolean b = m.matches();
System.out.println(b);
//这个是判断功能,但是如果做判断,这样做就有点麻烦了,我们直接用字符串的方法做
String s = "aaaaab";
String regex = "a*b";
boolean bb = s.matches(regex);
System.out.println(bb);
}
}
1.5 Pattern 匹配模式
Pattern类为正则表达式的编译表示形式。指定为字符串的表达式必须首先被编译为此类的实例。然后,可将得到的模式用于创建Matcher对象,依照正则表达式,该对象可与任意字符序列匹配。执行匹配所涉及的所有状态都驻留在匹配器中,所以多个匹配器可以共享同一个模式。
方法声明 | 功能描述 |
---|---|
compile() | 把正则表达式编译成匹配模式 |
matcher() | 根据匹配模式去匹配指定的字符串,得到匹配器 |
1.6 Matcher 匹配器
方法声明 | 功能描述 |
---|---|
matches() | 匹配字符串 |
find() | 查找有没有满足条件的子串 |
group() | 获取满足条件的子串 |
reset() | 将Matcher的状态重新设置为最初的状态 |
reset(CharSequence input) | 重新设置Matcher的状态,并且将候选字符序列设置为input后进行Matcher, 这个方法和重新创建一个Matcher一样,只是这样可以重用以前的对象。 |
start() | 返回Matcher所匹配的字符串在整个字符串的的开始下标 |
start(int group) | 指定你感兴趣的sub group,然后返回sup group(子分组)匹配的开始位置。 |
end() | 返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量。 |
- 注意事项
Pattern类为正则表达式的编译表示形式。指定为字符串的正则表达式必须首先被编译为此类的实例。然后,可将得到的模式用于创建Matcher对象,依照正则表达式,该对象可以与任意字符序列匹配。执行匹配所涉及的所有状态都驻留在匹配器中,所以多个匹配器可以共享同一模式
分组:简单的说,分组其实就是为了能够指定同一个规则可以使用多少次。正则表达式中的分组就是整个大的正则表达式和用()圈起来的内容。
在这个正则表达式”\w(\d\d)(\w+)”中
- 分组0:是”\w(\d\d)(\w+)”
- 分组1:是(\d\d)
- 分组2:是(\w+)
如果我们稍稍变换一下,将原先的正则表达式改为”(\w)(\d\d)(\w+)”,我们的分组就变成了
- 分组0:是”\w(\d\d)(\w+)”
- 分组1:是”(\w)”
- 分组2:是”(\d\d)”
- 分组3:是”(\w+)”
我们看看和正则表达式”\w(\d\d)(\w+)”匹配的一个字符串A22happy
- group(0)是匹配整个表达式的字符串的那部分A22happy
- group(1)是第1组(\d\d)匹配的部分:22
- group(2)是第2组(\w+)匹配的那部分happy
public static void main(String[] args) {
String Regex="\\w(\\d\\d)(\\w+)";
String TestStr="A22happy";
Pattern p=Pattern.compile(Regex);
Matcher matcher=p.matcher(TestStr);
if (matcher.find()) {
int gc=matcher.groupCount();
for (int i = 0; i <= gc; i++) {
System.out.println("group "+i+" :"+matcher.group(i));
}
}
}
- start()方法的使用
public static void testStart(){
//创建一个 Matcher ,使用 Matcher.start()方法
String candidateString = "My name is Bond. James Bond.";
String matchHelper[] ={" ^"," ^"};
Pattern p = Pattern.compile("Bond");
Matcher matcher = p.matcher(candidateString);
//找到第一个 'Bond'的开始下标
matcher.find();
int startIndex = matcher.start();
System.out.println(candidateString);
System.out.println(matchHelper[0] + startIndex);
//找到第二个'Bond'的开始下标
matcher.find();
int nextIndex = matcher.start();
System.out.println(candidateString);
System.out.println(matchHelper[1] + nextIndex);
}
运行结果:
/**
* 测试matcher.group方法
*/
public static void testGroup() {
// 创建一个 Pattern
Pattern p = Pattern.compile("Bond");
// 创建一个 Matcher ,以便使用 Matcher.group() 方法
String candidateString = "My name is Bond. James Bond.";
Matcher matcher = p.matcher(candidateString);
// 提取 group
matcher.find();
System.out.println(String.format("group匹配的字符串 : %s",matcher.group()));
System.out.println(String.format("匹配的开始位置 : %d", matcher.start()));
System.out.println(String.format("匹配的结束位置 : %d", matcher.end()));
System.out
.println("---再次使用matcher.find()方法,看看matcher中group、start、end方法的效果");
matcher.find();
System.out.println(String.format("group匹配的字符串 : %s",matcher.group()));;
System.out.println(String.format("匹配的开始位置 : %d", matcher.start()));
System.out.println(String.format("匹配的结束位置 : %d", matcher.end()));
System.out.println(String.format("candidateString字符串的长度 : %d", candidateString.length()));
}
运行结果:
- 获取由三个字符组成的单词
package cn.itcast_05;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
* 获取功能:
* 获取下面这个字符串中由三个字符组成的单词
* da jia ting wo shuo,jin tian yao xia yu,bu shang wan zi xi,gao xing bu?
*/
public class RegexDemo2 {
public static void main(String[] args) {
// 定义字符串
String s = "da jia ting wo shuo,jin tian yao xia yu,bu shang wan zi xi,gao xing bu?";
// 规则
String regex = "\\b\\w{3}\\b";
// 把规则编译成模式对象
Pattern p = Pattern.compile(regex);
// 通过模式对象得到匹配器对象
Matcher m = p.matcher(s);
// 调用匹配器对象的功能
// 通过find方法就是查找有没有满足条件的子串
// public boolean find()
// boolean flag = m.find();
// System.out.println(flag);
// // 如何得到值呢?
// // public String group()
// String ss = m.group();
// System.out.println(ss);
//
// // 再来一次
// flag = m.find();
// System.out.println(flag);
// ss = m.group();
// System.out.println(ss);
while (m.find()) {
System.out.println(m.group());
}
// 注意:一定要先find(),然后才能group()
// IllegalStateException: No match found
// String ss = m.group();
// System.out.println(ss);
}
}
- 判断身份证:要么是15位,要么是18位,最后一位可以为字母,并写程序提出其中的年月日。
public static void main(String[] args) {
testID_Card();
}
public static void testID_Card() {
// 测试是否为合法的身份证号码
String[] strs = { "130681198712092019", "13068119871209201x",
"13068119871209201", "123456789012345", "12345678901234x",
"1234567890123" };
// 准备正则表达式(身份证有15位和18位两种,身份证的最后一位可能是字母)
String regex = "(\\d{14}\\w)|\\d{17}\\w";
// 准备开始匹配,判断所有的输入是否是正确的
Pattern regular = Pattern.compile(regex); // 创建匹配的规则Patter
StringBuilder sb = new StringBuilder();
// 遍历所有要匹配的字符串
for (int i = 0; i < strs.length; i++) {
Matcher matcher = regular.matcher(strs[i]);// 创建一个Matcher
sb.append("身份证: ");
sb.append(strs[i]);
sb.append(" 匹配:");
sb.append(matcher.matches());
System.out.println(sb.toString());
sb.delete(0, sb.length());// 清空StringBuilder的方法
}
GetBirthDay(strs);
}
private static void GetBirthDay(String[] strs) {
System.out.println("准备开始获取出生日期");
// 准备验证规则
Pattern BirthDayRegular = Pattern.compile("(\\d{6})(\\d{8})(.*)");
// .*连在一起就意味着任意数量的不包含换行的字符
Pattern YearMonthDayRegular = Pattern.compile("(\\d{4})(\\d{2})(\\d{2})");
for (int i = 0; i < strs.length; i++) {
Matcher matcher = BirthDayRegular.matcher(strs[i]);
if (matcher.matches()) {
Matcher matcher2 = YearMonthDayRegular.matcher(matcher.group(2));
if (matcher2.matches()) {
System.out.println(strs[i]+" 中的出生年月分解为: "+"年" + matcher2.group(1) + " 月:" + matcher2.group(2) + " 日:" + matcher2.group(3));
}
}
}
}
运行结果:
2. 正则表达式工具类
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 正则工具类 提供验证邮箱、手机号、电话号码、身份证号码、数字等方法
*/
public final class RegexUtils {
/**
* 验证Email
*
* @param email
* email地址,格式:zhangsan@sina.com,zhangsan@xxx.com.cn,xxx代表邮件服务商
* @return 验证成功返回true,验证失败返回false ^ :匹配输入的开始位置。 \:将下一个字符标记为特殊字符或字面值。
* :匹配前一个字符零次或几次。 + :匹配前一个字符一次或多次。 (pattern) 与模式匹配并记住匹配。 x|y:匹配 x 或
* y。 [a-z] :表示某个范围内的字符。与指定区间内的任何字符匹配。 \w :与任何单词字符匹配,包括下划线。
*
* {n,m} 最少匹配 n 次且最多匹配 m 次 $ :匹配输入的结尾。
*/
public static boolean checkEmail(String email) {
String regex = "^(\\w)+(\\.\\w+)*@(\\w)+((\\.\\w{2,3}){1,3})$";
return Pattern.matches(regex, email);
}
/**
* 验证身份证号码
*
* @param idCard
* 居民身份证号码15位或18位,最后一位可能是数字或字母
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkIdCard(String idCard) {
String regex = "[1-9]\\d{13,16}[a-zA-Z0-9]{1}";
return Pattern.matches(regex, idCard);
}
/**
* 验证手机号码(支持国际格式,+86135xxxx...(中国内地),+00852137xxxx...(中国香港))
*
* @param mobile
* 移动、联通、电信运营商的号码段
* <p>
* 移动的号段:134(0-8)、135、136、137、138、139、147(预计用于TD上网卡)
* 、150、151、152、157(TD专用)、158、159、187(未启用)、188(TD专用)
* </p>
* <p>
* 联通的号段:130、131、132、155、156(世界风专用)、185(未启用)、186(3g)
* </p>
* <p>
* 电信的号段:133、153、180(未启用)、189
* </p>
* <p>
* 虚拟运营商的号段:170
* </p>
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkMobile(String mobile) {
String regex = "(\\+\\d+)?1[34578]\\d{9}$";
return Pattern.matches(regex, mobile);
}
/**
* 验证固定电话号码
*
* @param phone
* 电话号码,格式:国家(地区)电话代码 + 区号(城市代码) + 电话号码,如:+8602085588447
* <p>
* <b>国家(地区) 代码 :</b>标识电话号码的国家(地区)的标准国家(地区)代码。它包含从 0 到 9
* 的一位或多位数字, 数字之后是空格分隔的国家(地区)代码。
* </p>
* <p>
* <b>区号(城市代码):</b>这可能包含一个或多个从 0 到 9 的数字,地区或城市代码放在圆括号——
* 对不使用地区或城市代码的国家(地区),则省略该组件。
* </p>
* <p>
* <b>电话号码:</b>这包含从 0 到 9 的一个或多个数字
* </p>
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkPhone(String phone) {
// String regex = "(\\+\\d+)?(\\d{3,4}\\-?)?\\d{7,8}$";
String regex = "^1\\d{10}$";
return Pattern.matches(regex, phone);
}
/**
* 验证整数(正整数和负整数)
*
* @param digit
* 一位或多位0-9之间的整数
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkDigit(String digit) {
String regex = "\\-?[1-9]\\d+";
return Pattern.matches(regex, digit);
}
/**
* 验证整数和浮点数(正负整数和正负浮点数)
*
* @param decimals
* 一位或多位0-9之间的浮点数,如:1.23,233.30
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkDecimals(String decimals) {
String regex = "\\-?[1-9]\\d+(\\.\\d+)?";
return Pattern.matches(regex, decimals);
}
/**
* 验证空白字符
*
* @param blankSpace
* 空白字符,包括:空格、\t、\n、\r、\f、\x0B
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkBlankSpace(String blankSpace) {
String regex = "\\s+";
return Pattern.matches(regex, blankSpace);
}
/**
* 验证中文
*
* @param chinese
* 中文字符
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkChinese(String chinese) {
String regex = "^[\u4E00-\u9FA5]+$";
return Pattern.matches(regex, chinese);
}
/**
* 验证日期(年月日)
*
* @param birthday
* 日期,格式:1992-09-03,或1992.09.03
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkBirthday(String birthday) {
String regex = "[1-9]{4}([-./])\\d{1,2}\\1\\d{1,2}";
return Pattern.matches(regex, birthday);
}
/**
* 验证URL地址
*
* @param url
* 格式:http://blog.csdn.net:80/xyang81/article/details/7705960? 或
* http://www.csdn.net:80
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkURL(String url) {
String regex = "(https?://(w{3}\\.)?)?\\w+\\.\\w+(\\.[a-zA-Z]+)*(:\\d{1,5})?(/\\w*)*(\\??(.+=.*)?(&.+=.*)?)?";
return Pattern.matches(regex, url);
}
/**
* 匹配中国邮政编码
*
* @param postcode
* 邮政编码
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkPostcode(String postcode) {
String regex = "[1-9]\\d{5}";
return Pattern.matches(regex, postcode);
}
/**
* 匹配IP地址(简单匹配,格式,如:192.168.1.1,127.0.0.1,没有匹配IP段的大小)
*
* @param ipAddress
* IPv4标准地址
* @return 验证成功返回true,验证失败返回false
*/
public static boolean checkIpAddress(String ipAddress) {
String regex = "[1-9](\\d{1,2})?\\.(0|([1-9](\\d{1,2})?))\\.(0|([1-9](\\d{1,2})?))\\.(0|([1-9](\\d{1,2})?))";
return Pattern.matches(regex, ipAddress);
}
public static boolean checkNickname(String nickname) {
String regex = "^[a-zA-Z0-9\u4E00-\u9FA5_]+$";
return Pattern.matches(regex, nickname);
}
public static boolean hasCrossSciptRiskInAddress(String str) {
String regx = "[`~!@#$%^&*+=|{}':;',\\[\\].<>~!@#¥%……&*——+|{}【】‘;:”“’。,、?-]";
if (str != null) {
str = str.trim();
Pattern p = Pattern.compile(regx, Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(str);
return m.find();
}
return false;
}
}