第4章 常见对象 - 正则表达式的应用

优质
小牛编辑
132浏览
2023-12-01

1. 正则表达式的应用

String 类提供的几个特殊方法

方法声明功能描述
matches()判断该字符串是否匹配指定的正则表达式
replaceAll()将该字符串所有匹配正则表达式的子串替换成指定的字符串
replaceFirst()将该字符串中第一个匹配正则表达式的子串替换成指定的字符串
split(String regex)以regex为分隔符,将该字符串分割成多个子串

1.1 匹配功能

  1. public boolean matches(String regex) // 编译给定正则表达式并尝试将给定输入与其匹配。

校验邮箱

  1. package cn.itcast_02;
  2. import java.util.Scanner;
  3. /*
  4. * 校验邮箱
  5. *
  6. * 分析:
  7. * A:键盘录入邮箱
  8. * B:定义邮箱的规则
  9. * 1517806580@qq.com
  10. * liuyi@163.com
  11. * linqingxia@126.com
  12. * fengqingyang@sina.com.cn
  13. * fqy@itcast.cn
  14. * C:调用功能,判断即可
  15. * D:输出结果
  16. */
  17. public class RegexTest {
  18. public static void main(String[] args) {
  19. //键盘录入邮箱
  20. Scanner sc = new Scanner(System.in);
  21. System.out.println("请输入邮箱:");
  22. String email = sc.nextLine();
  23. //定义邮箱的规则
  24. //String regex = "[a-zA-Z_0-9]+@[a-zA-Z_0-9]{2,6}(\\.[a-zA-Z_0-9]{2,3})+";
  25. String regex = "\\w+@\\w{2,6}(\\.\\w{2,3})+";
  26. //调用功能,判断即可
  27. boolean flag = email.matches(regex);
  28. //输出结果
  29. System.out.println("flag:"+flag);
  30. }
  31. }

1.2 分割功能

  1. public String[] split(String regex) // 根据指定的正则表达式分割字符串

代码示例:我有如下一个字符串:”91 27 46 38 50”,请写代码实现最终输出结果是:”27 38 46 50 91”

  1. package cn.itcast_03;
  2. import java.util.Arrays;
  3. /*
  4. * 我有如下一个字符串:"91 27 46 38 50"
  5. * 请写代码实现最终输出结果是:"27 38 46 50 91"
  6. *
  7. * 分析:
  8. * A:定义一个字符串
  9. * B:把字符串进行分割,得到一个字符串数组
  10. * C:把字符串数组变换成int数组
  11. * D:对int数组排序
  12. * E:把排序后的int数组在组装成一个字符串
  13. * F:输出字符串
  14. */
  15. public class RegexTest {
  16. public static void main(String[] args) {
  17. // 定义一个字符串
  18. String s = "91 27 46 38 50";
  19. // 把字符串进行分割,得到一个字符串数组
  20. String[] strArray = s.split(" ");
  21. // 把字符串数组变换成int数组
  22. int[] arr = new int[strArray.length];
  23. for (int x = 0; x < arr.length; x++) {
  24. arr[x] = Integer.parseInt(strArray[x]);
  25. }
  26. // 对int数组排序
  27. Arrays.sort(arr);
  28. // 把排序后的int数组在组装成一个字符串
  29. StringBuilder sb = new StringBuilder();
  30. for (int x = 0; x < arr.length; x++) {
  31. sb.append(arr[x]).append(" ");
  32. }
  33. //转化为字符串
  34. String result = sb.toString().trim();
  35. //输出字符串
  36. System.out.println("result:"+result);
  37. }
  38. }

1.3 替换功能

  1. public String replaceAll(String regex,String replacement)

使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。

  • 论坛中不能出现数字字符,用*替换
  1. package cn.itcast_04;
  2. /*
  3. * 替换功能
  4. * String类的public String replaceAll(String regex,String replacement)
  5. * 使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
  6. */
  7. public class RegexDemo {
  8. public static void main(String[] args) {
  9. // 定义一个字符串
  10. String s = "helloqq12345worldkh622112345678java";
  11. // 我要去除所有的数字,用*给替换掉
  12. // String regex = "\\d+";
  13. // String regex = "\\d";
  14. //String ss = "*";
  15. // 直接把数字干掉
  16. String regex = "\\d+";
  17. String ss = "";
  18. String result = s.replaceAll(regex, ss);
  19. System.out.println(result);
  20. }
  21. }

1.4 获取功能

Pattern和Matcher类的使用

  1. package cn.itcast_05;
  2. import java.util.regex.Matcher;
  3. import java.util.regex.Pattern;
  4. /*
  5. * 获取功能
  6. * Pattern和Matcher类的使用
  7. *
  8. * 模式和匹配器的基本使用顺序
  9. */
  10. public class RegexDemo {
  11. public static void main(String[] args) {
  12. // 模式和匹配器的典型调用顺序
  13. // 把正则表达式编译成模式对象
  14. Pattern p = Pattern.compile("a*b");
  15. // 通过模式对象得到匹配器对象,这个时候需要的是被匹配的字符串
  16. Matcher m = p.matcher("aaaaab");
  17. // 调用匹配器对象的功能
  18. boolean b = m.matches();
  19. System.out.println(b);
  20. //这个是判断功能,但是如果做判断,这样做就有点麻烦了,我们直接用字符串的方法做
  21. String s = "aaaaab";
  22. String regex = "a*b";
  23. boolean bb = s.matches(regex);
  24. System.out.println(bb);
  25. }
  26. }

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
  1. public static void main(String[] args) {
  2. String Regex="\\w(\\d\\d)(\\w+)";
  3. String TestStr="A22happy";
  4. Pattern p=Pattern.compile(Regex);
  5. Matcher matcher=p.matcher(TestStr);
  6. if (matcher.find()) {
  7. int gc=matcher.groupCount();
  8. for (int i = 0; i <= gc; i++) {
  9. System.out.println("group "+i+" :"+matcher.group(i));
  10. }
  11. }
  12. }
  • start()方法的使用
  1. public static void testStart(){
  2. //创建一个 Matcher ,使用 Matcher.start()方法
  3. String candidateString = "My name is Bond. James Bond.";
  4. String matchHelper[] ={" ^"," ^"};
  5. Pattern p = Pattern.compile("Bond");
  6. Matcher matcher = p.matcher(candidateString);
  7. //找到第一个 'Bond'的开始下标
  8. matcher.find();
  9. int startIndex = matcher.start();
  10. System.out.println(candidateString);
  11. System.out.println(matchHelper[0] + startIndex);
  12. //找到第二个'Bond'的开始下标
  13. matcher.find();
  14. int nextIndex = matcher.start();
  15. System.out.println(candidateString);
  16. System.out.println(matchHelper[1] + nextIndex);
  17. }

运行结果:

正则表达式的应用 - 图1

  1. /**
  2. * 测试matcher.group方法
  3. */
  4. public static void testGroup() {
  5. // 创建一个 Pattern
  6. Pattern p = Pattern.compile("Bond");
  7. // 创建一个 Matcher ,以便使用 Matcher.group() 方法
  8. String candidateString = "My name is Bond. James Bond.";
  9. Matcher matcher = p.matcher(candidateString);
  10. // 提取 group
  11. matcher.find();
  12. System.out.println(String.format("group匹配的字符串 : %s",matcher.group()));
  13. System.out.println(String.format("匹配的开始位置 : %d", matcher.start()));
  14. System.out.println(String.format("匹配的结束位置 : %d", matcher.end()));
  15. System.out
  16. .println("---再次使用matcher.find()方法,看看matcher中group、start、end方法的效果");
  17. matcher.find();
  18. System.out.println(String.format("group匹配的字符串 : %s",matcher.group()));;
  19. System.out.println(String.format("匹配的开始位置 : %d", matcher.start()));
  20. System.out.println(String.format("匹配的结束位置 : %d", matcher.end()));
  21. System.out.println(String.format("candidateString字符串的长度 : %d", candidateString.length()));
  22. }

运行结果:

正则表达式的应用 - 图2

  • 获取由三个字符组成的单词
  1. package cn.itcast_05;
  2. import java.util.regex.Matcher;
  3. import java.util.regex.Pattern;
  4. /*
  5. * 获取功能:
  6. * 获取下面这个字符串中由三个字符组成的单词
  7. * da jia ting wo shuo,jin tian yao xia yu,bu shang wan zi xi,gao xing bu?
  8. */
  9. public class RegexDemo2 {
  10. public static void main(String[] args) {
  11. // 定义字符串
  12. String s = "da jia ting wo shuo,jin tian yao xia yu,bu shang wan zi xi,gao xing bu?";
  13. // 规则
  14. String regex = "\\b\\w{3}\\b";
  15. // 把规则编译成模式对象
  16. Pattern p = Pattern.compile(regex);
  17. // 通过模式对象得到匹配器对象
  18. Matcher m = p.matcher(s);
  19. // 调用匹配器对象的功能
  20. // 通过find方法就是查找有没有满足条件的子串
  21. // public boolean find()
  22. // boolean flag = m.find();
  23. // System.out.println(flag);
  24. // // 如何得到值呢?
  25. // // public String group()
  26. // String ss = m.group();
  27. // System.out.println(ss);
  28. //
  29. // // 再来一次
  30. // flag = m.find();
  31. // System.out.println(flag);
  32. // ss = m.group();
  33. // System.out.println(ss);
  34. while (m.find()) {
  35. System.out.println(m.group());
  36. }
  37. // 注意:一定要先find(),然后才能group()
  38. // IllegalStateException: No match found
  39. // String ss = m.group();
  40. // System.out.println(ss);
  41. }
  42. }
  • 判断身份证:要么是15位,要么是18位,最后一位可以为字母,并写程序提出其中的年月日。
  1. public static void main(String[] args) {
  2. testID_Card();
  3. }
  4. public static void testID_Card() {
  5. // 测试是否为合法的身份证号码
  6. String[] strs = { "130681198712092019", "13068119871209201x",
  7. "13068119871209201", "123456789012345", "12345678901234x",
  8. "1234567890123" };
  9. // 准备正则表达式(身份证有15位和18位两种,身份证的最后一位可能是字母)
  10. String regex = "(\\d{14}\\w)|\\d{17}\\w";
  11. // 准备开始匹配,判断所有的输入是否是正确的
  12. Pattern regular = Pattern.compile(regex); // 创建匹配的规则Patter
  13. StringBuilder sb = new StringBuilder();
  14. // 遍历所有要匹配的字符串
  15. for (int i = 0; i < strs.length; i++) {
  16. Matcher matcher = regular.matcher(strs[i]);// 创建一个Matcher
  17. sb.append("身份证: ");
  18. sb.append(strs[i]);
  19. sb.append(" 匹配:");
  20. sb.append(matcher.matches());
  21. System.out.println(sb.toString());
  22. sb.delete(0, sb.length());// 清空StringBuilder的方法
  23. }
  24. GetBirthDay(strs);
  25. }
  26. private static void GetBirthDay(String[] strs) {
  27. System.out.println("准备开始获取出生日期");
  28. // 准备验证规则
  29. Pattern BirthDayRegular = Pattern.compile("(\\d{6})(\\d{8})(.*)");
  30. // .*连在一起就意味着任意数量的不包含换行的字符
  31. Pattern YearMonthDayRegular = Pattern.compile("(\\d{4})(\\d{2})(\\d{2})");
  32. for (int i = 0; i < strs.length; i++) {
  33. Matcher matcher = BirthDayRegular.matcher(strs[i]);
  34. if (matcher.matches()) {
  35. Matcher matcher2 = YearMonthDayRegular.matcher(matcher.group(2));
  36. if (matcher2.matches()) {
  37. System.out.println(strs[i]+" 中的出生年月分解为: "+"年" + matcher2.group(1) + " 月:" + matcher2.group(2) + " 日:" + matcher2.group(3));
  38. }
  39. }
  40. }
  41. }

运行结果:

正则表达式的应用 - 图3

2. 正则表达式工具类

  1. import java.util.regex.Matcher;
  2. import java.util.regex.Pattern;
  3. /**
  4. * 正则工具类 提供验证邮箱、手机号、电话号码、身份证号码、数字等方法
  5. */
  6. public final class RegexUtils {
  7. /**
  8. * 验证Email
  9. *
  10. * @param email
  11. * email地址,格式:zhangsan@sina.com,zhangsan@xxx.com.cn,xxx代表邮件服务商
  12. * @return 验证成功返回true,验证失败返回false ^ :匹配输入的开始位置。 \:将下一个字符标记为特殊字符或字面值。
  13. * :匹配前一个字符零次或几次。 + :匹配前一个字符一次或多次。 (pattern) 与模式匹配并记住匹配。 x|y:匹配 x 或
  14. * y。 [a-z] :表示某个范围内的字符。与指定区间内的任何字符匹配。 \w :与任何单词字符匹配,包括下划线。
  15. *
  16. * {n,m} 最少匹配 n 次且最多匹配 m 次 $ :匹配输入的结尾。
  17. */
  18. public static boolean checkEmail(String email) {
  19. String regex = "^(\\w)+(\\.\\w+)*@(\\w)+((\\.\\w{2,3}){1,3})$";
  20. return Pattern.matches(regex, email);
  21. }
  22. /**
  23. * 验证身份证号码
  24. *
  25. * @param idCard
  26. * 居民身份证号码15位或18位,最后一位可能是数字或字母
  27. * @return 验证成功返回true,验证失败返回false
  28. */
  29. public static boolean checkIdCard(String idCard) {
  30. String regex = "[1-9]\\d{13,16}[a-zA-Z0-9]{1}";
  31. return Pattern.matches(regex, idCard);
  32. }
  33. /**
  34. * 验证手机号码(支持国际格式,+86135xxxx...(中国内地),+00852137xxxx...(中国香港))
  35. *
  36. * @param mobile
  37. * 移动、联通、电信运营商的号码段
  38. * <p>
  39. * 移动的号段:134(0-8)、135、136、137、138、139、147(预计用于TD上网卡)
  40. * 、150、151、152、157(TD专用)、158、159、187(未启用)、188(TD专用)
  41. * </p>
  42. * <p>
  43. * 联通的号段:130、131、132、155、156(世界风专用)、185(未启用)、186(3g)
  44. * </p>
  45. * <p>
  46. * 电信的号段:133、153、180(未启用)、189
  47. * </p>
  48. * <p>
  49. * 虚拟运营商的号段:170
  50. * </p>
  51. * @return 验证成功返回true,验证失败返回false
  52. */
  53. public static boolean checkMobile(String mobile) {
  54. String regex = "(\\+\\d+)?1[34578]\\d{9}$";
  55. return Pattern.matches(regex, mobile);
  56. }
  57. /**
  58. * 验证固定电话号码
  59. *
  60. * @param phone
  61. * 电话号码,格式:国家(地区)电话代码 + 区号(城市代码) + 电话号码,如:+8602085588447
  62. * <p>
  63. * <b>国家(地区) 代码 :</b>标识电话号码的国家(地区)的标准国家(地区)代码。它包含从 0 到 9
  64. * 的一位或多位数字, 数字之后是空格分隔的国家(地区)代码。
  65. * </p>
  66. * <p>
  67. * <b>区号(城市代码):</b>这可能包含一个或多个从 0 到 9 的数字,地区或城市代码放在圆括号——
  68. * 对不使用地区或城市代码的国家(地区),则省略该组件。
  69. * </p>
  70. * <p>
  71. * <b>电话号码:</b>这包含从 0 到 9 的一个或多个数字
  72. * </p>
  73. * @return 验证成功返回true,验证失败返回false
  74. */
  75. public static boolean checkPhone(String phone) {
  76. // String regex = "(\\+\\d+)?(\\d{3,4}\\-?)?\\d{7,8}$";
  77. String regex = "^1\\d{10}$";
  78. return Pattern.matches(regex, phone);
  79. }
  80. /**
  81. * 验证整数(正整数和负整数)
  82. *
  83. * @param digit
  84. * 一位或多位0-9之间的整数
  85. * @return 验证成功返回true,验证失败返回false
  86. */
  87. public static boolean checkDigit(String digit) {
  88. String regex = "\\-?[1-9]\\d+";
  89. return Pattern.matches(regex, digit);
  90. }
  91. /**
  92. * 验证整数和浮点数(正负整数和正负浮点数)
  93. *
  94. * @param decimals
  95. * 一位或多位0-9之间的浮点数,如:1.23,233.30
  96. * @return 验证成功返回true,验证失败返回false
  97. */
  98. public static boolean checkDecimals(String decimals) {
  99. String regex = "\\-?[1-9]\\d+(\\.\\d+)?";
  100. return Pattern.matches(regex, decimals);
  101. }
  102. /**
  103. * 验证空白字符
  104. *
  105. * @param blankSpace
  106. * 空白字符,包括:空格、\t、\n、\r、\f、\x0B
  107. * @return 验证成功返回true,验证失败返回false
  108. */
  109. public static boolean checkBlankSpace(String blankSpace) {
  110. String regex = "\\s+";
  111. return Pattern.matches(regex, blankSpace);
  112. }
  113. /**
  114. * 验证中文
  115. *
  116. * @param chinese
  117. * 中文字符
  118. * @return 验证成功返回true,验证失败返回false
  119. */
  120. public static boolean checkChinese(String chinese) {
  121. String regex = "^[\u4E00-\u9FA5]+$";
  122. return Pattern.matches(regex, chinese);
  123. }
  124. /**
  125. * 验证日期(年月日)
  126. *
  127. * @param birthday
  128. * 日期,格式:1992-09-03,或1992.09.03
  129. * @return 验证成功返回true,验证失败返回false
  130. */
  131. public static boolean checkBirthday(String birthday) {
  132. String regex = "[1-9]{4}([-./])\\d{1,2}\\1\\d{1,2}";
  133. return Pattern.matches(regex, birthday);
  134. }
  135. /**
  136. * 验证URL地址
  137. *
  138. * @param url
  139. * 格式:http://blog.csdn.net:80/xyang81/article/details/7705960? 或
  140. * http://www.csdn.net:80
  141. * @return 验证成功返回true,验证失败返回false
  142. */
  143. public static boolean checkURL(String url) {
  144. String regex = "(https?://(w{3}\\.)?)?\\w+\\.\\w+(\\.[a-zA-Z]+)*(:\\d{1,5})?(/\\w*)*(\\??(.+=.*)?(&.+=.*)?)?";
  145. return Pattern.matches(regex, url);
  146. }
  147. /**
  148. * 匹配中国邮政编码
  149. *
  150. * @param postcode
  151. * 邮政编码
  152. * @return 验证成功返回true,验证失败返回false
  153. */
  154. public static boolean checkPostcode(String postcode) {
  155. String regex = "[1-9]\\d{5}";
  156. return Pattern.matches(regex, postcode);
  157. }
  158. /**
  159. * 匹配IP地址(简单匹配,格式,如:192.168.1.1,127.0.0.1,没有匹配IP段的大小)
  160. *
  161. * @param ipAddress
  162. * IPv4标准地址
  163. * @return 验证成功返回true,验证失败返回false
  164. */
  165. public static boolean checkIpAddress(String ipAddress) {
  166. 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})?))";
  167. return Pattern.matches(regex, ipAddress);
  168. }
  169. public static boolean checkNickname(String nickname) {
  170. String regex = "^[a-zA-Z0-9\u4E00-\u9FA5_]+$";
  171. return Pattern.matches(regex, nickname);
  172. }
  173. public static boolean hasCrossSciptRiskInAddress(String str) {
  174. String regx = "[`~!@#$%^&*+=|{}':;',\\[\\].<>~!@#¥%……&*——+|{}【】‘;:”“’。,、?-]";
  175. if (str != null) {
  176. str = str.trim();
  177. Pattern p = Pattern.compile(regx, Pattern.CASE_INSENSITIVE);
  178. Matcher m = p.matcher(str);
  179. return m.find();
  180. }
  181. return false;
  182. }
  183. }