什么是正则表达式
正则表达式(Regular Expression,简写为regex、regexp或RE)是一种强大的文本处理工具,它是一串特殊的字符序列,用于描述和匹配字符串中的模式。正则表达式可以用来搜索、替换、提取符合特定规则的文本内容,并且广泛应用于各种编程语言、文本编辑器、数据库查询语言以及命令行工具中。
在正则表达式中,普通字符代表其字面含义,而特殊字符(元字符)则具有特殊意义,比如 .
可以匹配任意单个字符,\d
可以匹配任何数字,*
表示前面的元素可以重复0次或多次等。通过组合这些元字符和普通字符,可以创建复杂的模式来识别字符串中的复杂结构。
例如:
"a+b"
匹配包含一个或多个连续 "a" 后跟着一个 "b" 的字符串,如 "aab", "aaab", "aaaab" 等。"\\d{3}-\\d{2}-\\d{4}"
用于匹配美国社会安全号码格式,如 "123-45-6789"。
正则表达式的用途包括但不限于:
- 验证输入数据格式是否正确,例如检查电子邮件地址、电话号码或者日期格式。
- 在大量文本中搜索特定类型的文本片段。
- 替换文本中的特定模式,实现批量替换操作。
- 提取符合某种模式的数据,如从网页源码中抽取URL或电子邮件地址。
正则表达式语法在不同的编程语言或工具中可能会有细微差异,但基本原理和大部分元字符是通用的。
Java中的正则表达式
在Java中,正则表达式主要通过 java.util.regex
包中的两个类 Pattern
和 Matcher
来实现对字符串的匹配、查找、替换等操作。以下是在Java中使用正则表达式的常见步骤:
-
创建Pattern对象:
使用
Pattern.compile(String regex)
方法编译一个正则表达式字符串,生成一个Pattern
对象。String regex = "^[A-Za-z0-9]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$"; // 邮箱地址正则 Pattern pattern = Pattern.compile(regex);
-
创建Matcher对象:
用已编译的
Pattern
对象和需要进行匹配的字符串创建一个Matcher
对象。String email = "user@example.com"; Matcher matcher = pattern.matcher(email);
-
执行匹配操作:
-
matches()
方法:检查整个输入字符串是否完全符合给定的正则表达式。if (matcher.matches()) { System.out.println("邮箱格式正确"); } else { System.out.println("邮箱格式错误"); }
-
find()
方法:查找输入字符串中是否存在符合正则表达式的子串,并返回是否找到至少一个匹配项。while (matcher.find()) { System.out.println("找到匹配项: " + matcher.group()); }
-
-
提取匹配信息:
group(int group)
或group()
方法用于获取与正则表达式中括号分组对应的匹配部分。
String matchedString = matcher.group();
-
替换操作:
可以使用
String
类的replaceAll(String regex, String replacement)
或Pattern
的matcher(CharSequence input).replaceAll(String replacement)
方法来替换文本中的匹配项。String text = "Hello, world!"; String replacedText = text.replaceAll("world", "Java"); System.out.println(replacedText); // 输出 "Hello, Java!"
-
其他方法:
lookingAt()
方法:尝试从输入字符串的起始位置开始匹配。start()
,end()
方法:获取匹配到的子串在原字符串中的起始和结束索引。
通过以上方式,Java提供了强大的正则表达式支持,可以用来完成各种复杂的字符串处理任务。
java正则表达式规则
Java中的正则表达式遵循Perl 5风格的规则,以下是一些基本和常用的正则表达式元字符及规则:
-
单个字符匹配:
.
匹配任意一个字符(除了换行符)。\d
匹配数字(等同于[0-9]
)。\D
匹配非数字字符。\w
匹配字母、数字或下划线(等同于[a-zA-Z0-9_]
)。\W
匹配任何非字母、数字或下划线的字符。\s
匹配任何空白字符(包括空格、制表符、换页符等)。\S
匹配任何非空白字符。
-
量词:
?
表示前面的元素出现0次或1次(可选)。*
表示前面的元素可以出现任意次数,包括0次(重复任意次)。+
表示前面的元素至少出现1次(至少重复一次)。{n}
表示前面的元素必须出现n次。{n,}
表示前面的元素至少出现n次,可以无限多次。{n, m}
表示前面的元素最少出现n次,最多出现m次。
-
边界匹配:
^
表示匹配输入字符串的开始位置。$
表示匹配输入字符串的结束位置。\b
匹配单词边界。\B
匹配非单词边界。
-
分组与引用:
()
用于创建捕获组,括号内的模式会被作为一个整体对待,并且可以通过\n
(其中n是组号)在后向引用中引用该组的内容。(?:...)
非捕获组,不会保存匹配结果供后续引用。
-
选择和并集:
|
表示逻辑“或”,例如A|B
匹配 "A" 或者 "B"。
-
字符类:
[]
中列出的字符表示任何一个都可以匹配,例如[abc]
匹配 "a"、"b" 或 "c";[^abc]
匹配除 "a"、"b" 和 "c" 外的任何字符。
-
转义字符:
\
反斜杠用于转义特殊字符,如要匹配实际的(
、)
、.
、*
等字符,需在其前加\
。
-
预定义字符类:
\p{...}
用于Unicode字符属性的匹配,比如\p{L}
匹配任何Unicode字母,\p{Digit}
匹配任何Unicode数字。
在Java代码中使用正则表达式时,通常会先用 Pattern.compile(regex)
编译正则表达式,然后通过 matcher(String input)
方法得到一个 Matcher
对象来对实际文本进行操作。
常见的一些案例
在Java中,正则表达式被广泛用于字符串的匹配、查找、替换等操作。以下是一些常用的正则表达式案例及其用途:
-
验证电子邮件地址:
String emailPattern = "^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$"; Pattern pattern = Pattern.compile(emailPattern); Matcher matcher = pattern.matcher(userInputEmail); if (matcher.matches()) { System.out.println("邮箱格式正确"); } else { System.out.println("邮箱格式错误"); }
-
验证手机号码(例如中国手机号):
// 适用于国内13、14、15、16、17、18、19开头的11位手机号 String phonePattern = "(^(13|14|15|16|17|18|19)[0-9]{9}$)"; Pattern phoneRegex = Pattern.compile(phonePattern); Matcher matcher = phoneRegex.matcher(userInputPhone); if (matcher.matches()) { System.out.println("手机号码格式正确"); } else { System.out.println("手机号码格式错误"); } // 根据之前的记录,针对旧版部分号码段 // String oldPhonePattern = "(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\\d{8}$";
-
验证URL:
String urlPattern = "^https?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+$"; Pattern urlRegex = Pattern.compile(urlPattern); Matcher urlMatcher = urlRegex.matcher(userInputUrl); if (urlMatcher.matches()) { System.out.println("URL格式正确"); } else { System.out.println("URL格式错误"); }
-
验证IPv4地址:
String ipv4Pattern = "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"; Pattern ipv4Regex = Pattern.compile(ipv4Pattern); Matcher ipv4Matcher = ipv4Regex.matcher(userInputIp); if (ipv4Matcher.matches()) { System.out.println("IPv4地址格式正确"); } else { System.out.println("IPv4地址格式错误"); }
-
验证纯数字:
String numberPattern = "^\\d+$"; Pattern numberRegex = Pattern.compile(numberPattern); Matcher numberMatcher = numberRegex.matcher(userInputNumber); if (numberMatcher.matches()) { System.out.println("输入内容全部为数字"); } else { System.out.println("输入内容包含非数字字符"); }
-
提取JSON或XML中的键值对:
// JSON中键值对:"{\"key\":\"value\"}" String jsonKeyValPattern = "\"(.*?)\":\\s*\"(.*?)\""; Pattern jsonRegex = Pattern.compile(jsonKeyValPattern); Matcher jsonMatcher = jsonRegex.matcher(jsonString); while (jsonMatcher.find()) { System.out.println("Key: " + jsonMatcher.group(1) + ", Value: " + jsonMatcher.group(2)); } // XML中键值对:<key>value</key> String xmlKeyValPattern = "<(\\w+)>([^<]+)</\\1>"; Pattern xmlRegex = Pattern.compile(xmlKeyValPattern); Matcher xmlMatcher = xmlRegex.matcher(xmlString); while (xmlMatcher.find()) { System.out.println("Key: " + xmlMatcher.group(1) + ", Value: " + xmlMatcher.group(2)); }
-
去除字符串中的HTML标签:
String htmlTagsPattern = "<[^>]+>"; Pattern htmlTagsRegex = Pattern.compile(htmlTagsPattern); String cleanedText = htmlTagsRegex.matcher(htmlContent).replaceAll("");
-
验证日期格式(例如YYYY-MM-DD):
String datePattern = "^\\d{4}-\\d{2}-\\d{2}$"; Pattern dateRegex = Pattern.compile(datePattern); Matcher dateMatcher = dateRegex.matcher(userInputDate); if (dateMatcher.matches()) { System.out.println("日期格式正确"); } else { System.out.println("日期格式错误"); }
-
提取URL中的域名部分:
String urlDomainPattern = "(http[s]?://)?(www\\.)?([^/]*\\.)*([a-zA-Z0-9][-a-zA-Z0-9]{0,62})[.]([a-z]{2,6})"; Pattern domainRegex = Pattern.compile(urlDomainPattern); Matcher domainMatcher = domainRegex.matcher(fullUrl); if (domainMatcher.find()) { String domain = domainMatcher.group(domainMatcher.groupCount()); System.out.println("域名是: " + domain); }
-
匹配和替换文本中的电话号码(仅示例部分手机号码):
// 匹配以1开头的11位数字(简化版中国手机号) String phoneExtractPattern = "(1\\d{10})"; Pattern phoneExtractRegex = Pattern.compile(phoneExtractPattern); // 替换为星号隐藏中间四位 String phoneMaskPattern = "(\\d{3})\\d{4}(\\d{4})"; Pattern phoneMaskRegex = Pattern.compile(phoneMaskPattern); String maskedPhone = phoneMaskRegex.matcher(originalPhone).replaceAll("$1****$2");
-
检查密码强度(至少包含一个大写字母、一个小写字母、一个数字和一个特殊字符,长度在8-16之间):
String passwordPattern = "^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[@$!%*#?&])[A-Za-z\\d@$!%*#?&]{8,16}$"; Pattern passwordRegex = Pattern.compile(passwordPattern); Matcher passwordMatcher = passwordRegex.matcher(userInputPassword); if (passwordMatcher.matches()) { System.out.println("密码强度符合要求"); } else { System.out.println("密码强度不符合要求"); }
-
验证用户名(仅包含字母、数字和下划线,且首字符不能为数字):
String usernamePattern = "^[a-zA-Z][a-zA-Z0-9_]*$"; Pattern usernameRegex = Pattern.compile(usernamePattern); Matcher usernameMatcher = usernameRegex.matcher(userInputUsername); if (usernameMatcher.matches()) { System.out.println("用户名格式正确"); } else { System.out.println("用户名格式错误"); }
-
提取纯文本中的所有单词:
String wordsPattern = "\\b\\w+\\b"; Pattern wordsRegex = Pattern.compile(wordsPattern, Pattern.CASE_INSENSITIVE); Matcher wordsMatcher = wordsRegex.matcher(textContent); while (wordsMatcher.find()) { System.out.println("找到的单词: " + wordsMatcher.group()); }
-
验证信用卡号(简单的Luhn校验算法匹配):
// 这个正则表达式不执行完整的Luhn校验算法,只是检查基本的卡号格式 String creditCardPattern = "^\\d{4}-?\\d{4}-?\\d{4}-?\\d{4}$"; Pattern creditCardRegex = Pattern.compile(creditCardPattern); Matcher creditCardMatcher = creditCardRegex.matcher(userInputCreditCard); if (creditCardMatcher.matches()) { System.out.println("信用卡号格式正确,但请注意这并未进行完整的Luhn校验"); } else { System.out.println("信用卡号格式错误"); } // 对于完整的Luhn校验,需要编写额外的逻辑计算校验码
-
去除字符串两端的空白字符:
String trimPattern = "^\\s+|\\s+$"; Pattern trimRegex = Pattern.compile(trimPattern); String trimmedString = trimRegex.matcher(originalString).replaceAll(""); System.out.println("去除两端空白后的字符串: " + trimmedString);
-
验证邮政编码(以美国邮政编码为例):
String zipCodePattern = "^\\d{5}(?:[-\\s]\\d{4})?$"; Pattern zipCodeRegex = Pattern.compile(zipCodePattern); Matcher zipCodeMatcher = zipCodeRegex.matcher(userInputZipCode); if (zipCodeMatcher.matches()) { System.out.println("邮政编码格式正确"); } else { System.out.println("邮政编码格式错误"); }
-
提取字符串中的纯数字序列:
String numbersPattern = "\\d+"; Pattern numbersRegex = Pattern.compile(numbersPattern); Matcher numbersMatcher = numbersRegex.matcher(textWithNumbers); while (numbersMatcher.find()) { System.out.println("找到的数字: " + numbersMatcher.group()); }
-
检查是否为有效的IPv6地址:
String ipv6Pattern = "^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$"; Pattern ipv6Regex = Pattern.compile(ipv6Pattern); Matcher ipv6Matcher = ipv6Regex.matcher(userInputIPv6); if (ipv6Matcher.matches()) { System.out.println("IPv6地址格式正确"); } else { System.out.println("IPv6地址格式错误"); }
-
匹配和替换文本中的HTML实体字符:
// 匹配HTML实体字符 String htmlEntityPattern = "&(#?\\w+);"; Pattern htmlEntityRegex = Pattern.compile(htmlEntityPattern); // 替换为实际字符 String decodedText = Html.fromHtml(originalHtml).toString();
-
检测密码中是否存在连续重复字符(例如"123333"或"abcdd"):
String consecutiveCharsPattern = "(.)\\1{2,}"; Pattern consecutiveCharsRegex = Pattern.compile(consecutiveCharsPattern); Matcher consecutiveCharsMatcher = consecutiveCharsRegex.matcher(password); if (consecutiveCharsMatcher.find()) { System.out.println("密码包含连续重复字符,不符合要求"); } else { System.out.println("密码不含连续重复字符"); }