一、什么是 Java 正则表达式
Java 正则表达式是一个用于匹配字符串的模板,由字符和特殊字符组成,可用于查找、替换、验证特定的模式。在 Java 中,我们可以使用 java.util.regex 包中的类来操作正则表达式。
正则表达式在 Java 编程中发挥着重要作用。它可以被看作是一种定义字符串规则的工具,通过特定的模式来匹配、查找、替换和验证字符串。例如,我们可以使用正则表达式来验证用户输入的邮箱地址是否合法,或者从一段文本中提取特定的信息。
在 Java 中操作正则表达式,首先需要导入 java.util.regex 包。该包提供了两个主要的类:Pattern 和 Matcher,它们用于表示正则表达式和进行匹配操作。
首先,我们需要创建一个正则表达式模式,可以使用 Pattern.compile () 方法,并传入需要匹配的正则表达式作为参数。比如,我们可以创建一个匹配邮箱地址的正则表达式模式:Pattern pattern = Pattern.compile ("[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[a-zA-Z0-9]+");
接下来,我们可以使用创建的正则表达式模式进行匹配操作。我们需要使用 Matcher 类的 matcher () 方法创建一个 Matcher 对象,然后使用 Matcher 对象的 find ()、matches ()、group () 等方法进行匹配操作。例如,假设我们有一个字符串 input,我们可以使用以下代码进行匹配操作:String input = " 我的邮箱是 example@example.com";Matcher matcher = pattern.matcher (input);if (matcher.find ()) {String email = matcher.group ();System.out.println (" 匹配到的邮箱:"+ email);} else {System.out.println (" 未找到匹配的内容 ");}
除了匹配操作之外,Java 的正则表达式还支持替换和拆分功能。可以使用 Matcher 类的 replaceAll ()、replaceFirst () 和 split () 等方法来实现。
总结一下,在 Java 中使用正则表达式,需要经历以下几个步骤:
导入 java.util.regex 包。 创建正则表达式模式:Pattern pattern = Pattern.compile ("正则表达式");。 创建 Matcher 对象并进行匹配操作:Matcher matcher = pattern.matcher ("需要匹配的字符串");。 使用 find ()、matches ()、group () 等方法进行匹配操作。 使用 replaceAll ()、replaceFirst () 和 split () 等方法进行替换和拆分操作。二、java.util.regex 包中的主要类
1. Pattern 和 Matcher 类
Pattern 类表示正则表达式的编译表示形式,通过 Pattern.compile () 方法创建。在 Java 中,Pattern类扮演着重要的角色。它是正则表达式在内存中的编译表示形式。要创建一个Pattern对象,我们必须使用Pattern.compile()方法,并传入一个正则表达式作为参数。例如,Pattern pattern = Pattern.compile("[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-zA-Z0-9]+");创建了一个用于匹配邮箱地址的Pattern对象。
Matcher 类用于对输入字符串进行匹配操作,通过 Pattern 对象的 matcher () 方法创建。Matcher类则是用于对输入字符串进行匹配操作的引擎。我们可以通过Pattern对象的matcher()方法来创建一个Matcher对象。例如,Matche
r macher = pattern.matcher(input);这里的pattern是一个已经创建好的Pattern对象,input是要进行匹配的字符串。
2. String 类中的相关方法
boolean matches (String regex):判断该字符串是否匹配指定的正则表达式。String类中的matches(String regex)方法用于判断该字符串是否匹配指定的正则表达式。如果字符串完全匹配正则表达式,则返回true,否则返回false。例如,"example@example.com".matches("[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-zA-Z0-9]+");可以判断一个字符串是否是一个合法的邮箱地址。
String replaceAll (String regex,String replacement):将该字符串中所有匹配 regex 的子串替换成 replacement。 replaceAll(String regex,String replacement)方法可以将字符串中所有匹配指定正则表达式的子串替换成给定的replacement。例如,String cent="有关的数据,有的可1以直2接进3行舍去";System.out.println(cent.replaceAll("\\\\d", ""));这里将字符串cent中的所有数字替换为空字符串。tString replaceFirst (String regex,String replacement):将该字符串中第一个匹配 regex 的子串替换成 replacement。replaceFirst(String regex,String replacement)方法用于将字符串中第一个匹配指定正则表达式的子串替换成给定的replacement。与replaceAll不同的是,它只替换第一个匹配的子串。
String [] split (String regex):以 regex 作为分隔符,把该字符串分割成多个子串。split(String regex)方法以指定的正则表达式作为分隔符,将字符串分割成多个子串,并返回一个字符串数组。例如,String names = "小路dhdfhdf342蓉儿43fdffdfbjdfaf小何";String[] arrs = names.split("\\\\w+");这里将字符串names按照非单词字符进行分割。
三、正则表达式的语法
1. 特殊字符
在 Java 正则表达式中,特殊字符具有特定的用途。例如,反斜线(\)在正则表达式中有特殊的意义。在 Java 的正则表达式中,两个 “\” 代表其他语言中的一个 “\”。比如,要表示一个普通的反斜线,需要用 “\\”。此外,还有一些特殊字符,如 “\0n”(八进制值的字符 0n,其中 0 <= n <= 7)、“\0nn”(八进制值的字符 0nn,0 <= n <= 7)、“\0mnn”(八进制值的字符 0mnn,0 <= m <= 3,0 <= n <= 7)、“\xhh”(十六进制值的字符 0xhh)、“\uhhhh”(十六进制值的字符 0xhhhh)、“\t”(制表符)、“\n”(换行符)、“\r”(回车符)、“\f”(换页符)、“\a”(响铃符)、“\e”(转义符)等。
2. 预定义字符方括号表达式
预定义字符方括号表达式在 Java 正则表达式中有多种用法。
字符集:方括号用于定义一个字符类,用来指定一个字符的集合。例如,正则表达式 “[abc]” 匹配任何包含字符 “a”、“b” 或 “c” 的字符串。方括号中的字符可以是任意的字母、数字或特殊字符,且字符是无序的。 字符范围:方括号中还可以使用连字符(-)来定义字符的范围。例如,“[a-z]” 匹配任何小写字母,“[A-Z]” 匹配任何大写字母。 反向范围字符:在方括号的开头加上 “^” 字符可以对字符类进行取反操作。例如,“[^0-9]” 匹配任何非数字字符。3. 边界匹配符
Java 正则表达式中的边界匹配符有特定的用途。
“^”:匹配字符串的开头。例如,正则表达式 “^abc” 可以匹配 “abc”、“abcdef”,但不能匹配 “xabc”。 “ ” 可以匹配 “abc”、“xabc”,但不能匹配 “abcdef”。 “\b”:匹配单词的边界。 “\B”:非单词的边界。 “\A”:输入的开头。 “\G”:前一个匹配的结尾。 “\Z”:输入的结尾,仅用于最后的结束符。 “\z”:输入的结尾。4. 数量标识符
Java 正则表达式支持三种数量表示符的用法。
贪婪模式(Greedy):数量表示符默认采用贪婪模式,除非另有表示。贪婪模式的表达式会一直匹配下去,直到无法匹配为止。例如,从 “hello,java!” 字符串中查找匹配 “\w*” 子串时,因为 “\w” 使用了贪婪模式,数量表示符会一直匹配下去,所以该字符串前面的所有单词字符都被它匹配到,直到遇到空格,所以替换后的效果是 “■,java!”。 勉强模式(Reluctant):用问号后缀(?)表示,它只会匹配最少的字符。也称为最小匹配模式。例如,从 “hello,java!” 字符串中查找匹配 “\w*?” 子串时,数量表示符会尽量匹配最少字符,即匹配 0 个字符,所以替换后的结果是 “■hello,java!”。 占有模式(Possessive):用加号后缀(+)表示,目前只有 Java 支持占有模式,通常比较少用。四、正则表达式的实例应用
1. 常用验证(手机号、身份证号、邮箱)
在 Java 中,我们可以使用正则表达式来验证手机号、身份证号和邮箱的有效性。以下是具体的实现方法:
手机号验证:
中国的手机号通常以特定的数字开头,后面跟着一定数量的数字。我们可以使用正则表达式来匹配这些特征。例如:
public static boolean isMobile(final String str) { Pattern p = null; Matcher m = null; boolean b = false; p = Pattern.compile("^[1][3,4,5,7,8][0-9]{9}$"); m = p.matcher(str); b = m.matches(); return b;}
这个方法使用正则表达式^[1][3,4,5,7,8][0-9]{9}$来验证手机号。它首先创建一个Pattern对象,然后使用该对象创建一个Matcher对象。最后,通过调用matches方法来判断输入的字符串是否符合手机号的格式。
身份证号验证:
身份证号的验证相对复杂一些,需要考虑更多的规则。以下是一个示例代码:
// 省份数据private static Map<Integer, String> provs = new HashMap<>();static { provs.put(11, "北京"); provs.put(12, "天津"); //... 其他省份数据}// 验证身份号前 18 位private static boolean checkCode(String cert) { String regex = "^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$"; if (RegularUtils.validate(regex, cert)) { // 校验合算法 int[] factor = new int[]{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; String[] parity = new String[]{"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"}; String code = cert.substring(17); int sum = 0; for (int i = 0; i < 17; i++) { sum += Integer.parseInt(String.valueOf(cert.charAt(i))) * factor[i]; } if (parity[sum % 11].equals(code.toUpperCase())) { return true; } return false; } return false;}// 组合起来,分段验证,提高效率public static boolean vlidateIdcard(String cert) { if (checkCode(cert)) { String date = cert.substring(6, 14); if (checkDate(date)) { if (checkProv(cert.substring(0, 2))) { return true; } return false; } } return false;}// 验证年private static boolean checkDate(String date) { String pattern = "^(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)$"; if (RegularUtils.validate(pattern, date)) { String month = date.substring(4, 6); try { Date date2 = DateUtils.convertString2Date("yyyyMMdd", date); if (date2!= null && date2.getMonth() == (Integer.parseInt(month) - 1)) { return true; } } catch (Exception e) { // TODO: handle exception } return false; } return false;}// 检查省份private static boolean checkProv(String prov) { String pattern = "^[1-9][0-9]"; if (RegularUtils.validate(pattern, prov)) { return provs.containsKey(Integer.parseInt(prov)); } return false;}
这个方法通过多个辅助方法来验证身份证号的有效性。首先,使用正则表达式^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$来验证身份证号的格式。然后,通过校验码算法、日期验证和省份验证来进一步确保身份证号的合法性。
邮箱验证:
邮箱的格式通常有一定的规则,我们可以使用正则表达式来验证邮箱的有效性。以下是一个示例代码:
public static boolean isEmail(String email) { String str = "^([a-zA-Z0-9]*[-_]?[a-zA-Z0-9]+)*@([a-zA-Z0-9]*[-_]?[a-zA-Z0-9]+)+[\\.][A-Za-z]{2,3}([\\.][A-Za-z]{2})?$"; Pattern p = Pattern.compile(str); Matcher m = p.matcher(email); return m.matches();}
这个方法使用正则表达式^([a-zA-Z0-9]*[-_]?[a-zA-Z0-9]+)*@([a-zA-Z0-9]*[-_]?[a-zA-Z0-9]+)+[\\.][A-Za-z]{2,3}([\\.][A-Za-z]{2})?$来验证邮箱的格式。它首先创建一个Pattern对象,然后使用该对象创建一个Matcher对象。最后,通过调用matches方法来判断输入的字符串是否符合邮箱的格式。
2. 判断字符串是否满足正则表达式
我们可以通过实例代码演示如何判断一个字符串是否满足特定的正则表达式。例如:
public static boolean validatePhoneNumber(String phoneNumber) { String regex = "^1[3-9]\\d{9}$"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(phoneNumber); return matcher.matches();}
这个方法使用正则表达式^1[3-9]\\d{9}$来验证手机号。它首先创建一个Pattern对象,然后使用该对象创建一个Matcher对象。最后,通过调用matches方法来判断输入的字符串是否符合手机号的格式。如果字符串满足正则表达式,matches方法将返回true,否则返回false。
3. 判断字符串是否包含正则表达式表示的字符串
我们可以使用正则表达式来判断一个字符串是否包含特定正则表达式表示的子串。例如:
String passwd = "rqbkjhrjqh1111@!45";String regex = "^[A-Za-z]|[0-9]|[!@#$%^&*]{6,18}$";if (!passwd.matches(regex)) { return false; // 验证不通过}
这个代码片段首先定义了一个正则表达式^[A-Za-z]|[0-9]|[!@#$%^&*]{6,18}$,然后使用matches方法来判断字符串passwd是否符合这个正则表达式。如果字符串不包含正则表达式表示的子串,matches方法将返回false。
4. 分组匹配
正则表达式的分组功能可以让我们更灵活地处理匹配结果。以下是通过实例代码展示如何获取分组匹配的结果:
import java.util.regex.Matcher;import java.util.regex.Pattern;public class RegexGroupExample { public static void main(String[] args) { String input = "Hello, my name is John Doe"; String regex = "(\\w+), my name is (\\w+) (\\w+)"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(input); if (matcher.find()) { System.out.println("Full match: " + matcher.group(0)); System.out.println("First group match: " + matcher.group(1)); System.out.println("Second group match: " + matcher.group(2)); System.out.println("Third group match: " + matcher.group(3)); } else { System.out.println("No match found"); } }}
在这个例子中,我们使用正则表达式(\\w+), my name is (\\w+) (\\w+)来匹配字符串Hello, my name is John Doe。这个正则表达式有三个分组,分别匹配逗号前的单词、名字的第一个单词和名字的第二个单词。通过Matcher类的group方法,我们可以获取到每个分组的匹配结果。