正则表达式
正则表达式: regular expression, 很多时候都简写为 regex.
正则表达式可以校验字符串是否满足一定的规则, 并用来校验数据格式的合法性.
Java 中, 正则表达式是以字符串的形式体现的.
程序示例:
public class Demo { public static void main(String[] args) { /* * 假如现在要求校验一个 qq 号码是否正确. * 规则: 6 位及 20 位之内, 0 不能在开头, 必须全部是数字. * 先使用目前所学知识完成校验需求然后体验一下正则表达式检验. */ String qq = "1234567890"; System.out.println(checkQQ(qq)); // true // 字符串有一个方法叫做 matches, 用来匹配正则表达式 System.out.println(qq.matches("[1-9]\\d{5,19}")); // true // 其他用途举例: // 校验用户名是否满足规则 // 校验密码是否满足规则 // 校验身份证是否满足规则 // 校验手机是否满足规则 } public static boolean checkQQ(String qq) { // 规则: 6 位及 20 位之内, 0 不能在开头, 必须全部是数字 . // 核心思想: // 先把异常数据进行过滤 // 下面的就是满足要求的数据了. int len = qq.length(); if (len < 6 || len > 20) { return false; } // 0 不能在开头 if (qq.startsWith("0")) { return false; } // 必须全部是数字 for (int i = 0; i < qq.length(); i++) { char c = qq.charAt(i); if (c < '0' | c > '9') { return false; } } return true; } }
正则表达式的作用
-
作用一: 校验字符串是否满足规则
-
作用二: 在一段文本中查找满足要求的内容
正则表达式中, 方括号表示范围.
正则表达式的匹配是从左到右一个一个地去匹配的.
[abc] 表示字符串只能出现 abc, 且只能出现一个.
^ 表示取反.


程序示例:
public class Demo2 { public static void main(String[] args) { System.out.println("ab".matches("[abc]")); // false String s = "abca"; System.out.println(s.matches("[abc]")); // false String ss = "abc"; System.out.println(ss.matches("[abc]")); // false String sss = "a"; System.out.println(sss.matches("[abc]")); // true System.out.println("ab".matches("[abc][abc]")); // true System.out.println("zz".matches("[^abc]")); // false System.out.println("zz".matches("[^abc][^abc]")); // true // 只能一个一个地匹配 System.out.println("a".matches("[ad]")); // true, 匹配 a 或者 d System.out.println("b".matches("[a-dp-z]")); // true, 匹配 a ~ d 或者 p ~ z } }
程序示例:
public class RegexDemo2 { public static void main(String[] args) { // public boolean Matches(String regex) : 判断是否与正则表达式匹配, 匹配返回 true // 只能是 a b c System.out.println("-----------1-------------"); System.out.println("a".matches("[abc]")); // true System.out.println("z".matches("[abc]")); // false // 不能出现 a b c System.out.println("-----------2-------------"); System.out.println("a".matches("[^abc]")); // false System.out.println("z".matches("[^abc]")); // true System.out.println("zz".matches("[^abc]")); // false System.out.println("zz".matches("[^abc][^abc]")); // true // a 到 zA 到 Z (包括头尾的范围) System.out.println("-----------3-------------"); System.out.println("a".matches("[a-zA-z]")); // true System.out.println("z".matches("[a-zA-z]")); // true System.out.println("aa".matches("[a-zA-z]"));// false System.out.println("zz".matches("[a-zA-Z]")); // false System.out.println("zz".matches("[a-zA-Z][a-zA-Z]")); // true System.out.println("0".matches("[a-zA-Z]"));// false System.out.println("0".matches("[a-zA-Z0-9]"));// true // [a-d[m-p]] a 到 d, 或 m 到 p System.out.println("-----------4-------------"); System.out.println("a".matches("[a-d[m-p]]"));// true System.out.println("d".matches("[a-d[m-p]]")); // true System.out.println("m".matches("[a-d[m-p]]")); // true System.out.println("p".matches("[a-d[m-p]]")); // true System.out.println("e".matches("[a-d[m-p]]")); // false System.out.println("0".matches("[a-d[m-p]]")); // false // [a-z&&[def]] a-z 和 def 的交集. 为: d, e, f // 细节: 如果要求两个范围的交集, 那么需要写符号 && // 如果写成了一个 &, 那么此时 & 表示就不是交集了, 而是一个简简单单的 & 符号 System.out.println("----------5------------"); System.out.println("a".matches("[a-z&[def]]")); // true System.out.println("&".matches("[a-z&[def]]")); // true System.out.println("&".matches("[a-z&&[def]]")); // false System.out.println("a".matches("[a-z&&[def]]")); // false System.out.println("d".matches("[a-z&&[def]]")); // true System.out.println("0".matches("[a-z&&[def]]")); // false // [a-z&&[^bc]] a-z 和 非 bc 的交集. (等同于 [ad-z]) System.out.println("-----------6------------_"); System.out.println("a".matches("[a-z&&[^bc]]"));// true System.out.println("b".matches("[a-z&&[^bc]]")); // false System.out.println("0".matches("[a-z&&[^bc]]")); // false // [a-z&&[^m-p]] a 到 z 和除了 m 到 p 的交集. (等同于 [a-1q-z]) System.out.println("-----------7-------------"); System.out.println("a".matches("[a-z&&[^m-p]]")); // true System.out.println("m".matches("[a-z&&[^m-p]]")); // false System.out.println("0".matches("[a-z&&[^m-p]]")); // false } }


程序示例:
public class RegexDemo3 { public static void main(String[] args) { // \ 转义字符: 改变后面那个字符原本的含义 // 练习: 以字符串的形式打印一个双引号 // " 在 Java 中表示字符串的开头或者结尾 // 此时 \ 表示转义字符, 改变了后面那个双引号原本的含义 // 把他变成了一个普普通通的双引号而已. System.out.println("\""); // \ 表示转义字符 // 两个 \ 的理解方式: 前面的 \ 是一个转义字符, 改变了后面 \ 原本的含义, 把他变成一个普普通通的 \ 而已. System.out.println("c:Users\\moon\\IdeaProjects\\basic-code\\myapi\\src\\com\\itheima\\a08regexdemo\\RegexDemo1.java"); // . 表示任意一个字符 System.out.println("----------------------- 1 ----------------------"); System.out.println("你".matches("..")); // false, 两个 . 需要匹配两个任意的字符 System.out.println("你".matches(".")); // true System.out.println("你a".matches(".."));// true // \d 表示任意的一个数字, 但是在写代码的时候, 第一个 \ 需要被转义, 两个 \ 表示一个 \, 所以要写成 \\d System.out.println("----------------------- 2 ----------------------"); System.out.println("a".matches("\\d")); // false System.out.println("3".matches("\\d")); // true System.out.println("333".matches("\\d")); // false System.out.println("333".matches("\\d\\d\\d")); // true // \w 只能是一位单词字符, 等同于 [a-zA-Z_0-9], 要写成 \\w System.out.println("----------------------- 3 ----------------------"); System.out.println("z".matches("\\w")); // true System.out.println("2".matches("\\w")); // true System.out.println("21".matches("\\w")); // false System.out.println("你".matches("\\w")); // false // 非单词字符 System.out.println("你".matches("\\W")); // true // 以上正则匹配只能校验单个字符. // 必须是数字, 字母, 下划线, 至少 6 位 System.out.println("----------------------- 4 ----------------------"); System.out.println("2442fsfsf".matches("\\w{6,}")); // true System.out.println("244f".matches("\\w{6,}")); // false // 必须是数字和字符, 必须是 4 位 System.out.println("----------------------- 5 ----------------------"); System.out.println("23dF".matches("[a-zA-Z0-9]{4}")); // true System.out.println("23 F".matches("[a-zA-Z0-9]{4}")); // false System.out.println("23dF".matches("[\\w&&[^_]]{4}")); // true System.out.println("23_F".matches("[\\w&&[^_]]{4}")); // false } }
在 API 帮助文档中搜索 Pattern 可以找到这些规则.

或者先找 String 类, 再找 matches 方法.

练习:
请使用正则表达式完成如下需求
请编写正则表达式验证用户输入的手机号码是否满足要求.
请编写正则表达式验证用户输入的邮箱号是否满足要求.
请编写正则表达式验证用户输入的电话号码是否满足要求.
实际工作中, 很少自己从零开始写正则表达式, 一般都是在搜索引擎中查到一个类似的, 再修改为自己需要的.
IDEA 插件: any-rule

在代码中需要书写正则表达式的地方, 按下鼠标右键可以进入插件, 查找自己需要的格式.


插件自动生成的正则表达式, 需要再进行修改, 比如, ^ 表示从开头进行匹配, $ 表示一直匹配到末尾, 而 matches() 方法默认就是从头到尾进行匹配的, 所以这两个符号要删除. 再比如, 要将 \
改为 \\
.
程序示例:
public class RegexDemo4 { public static void main(String[] args) { /* * 需求 * 请编写正则表达式验证用户输入的手机号码, 邮箱号码, 电话号码是否满足要求. * 验证手机号码 13112345678 13712345667 13945679027 139456790271 * 验证座机电话号码 020-2324242 02122442 027-42424 0712-3242434 * 验证邮箱号码 3232323@qq.com zhangsan@itcast.cnn dlei0009@163.com dlei0009@pci.com.cn */ // 心得: // 拿着一个正确的数据, 从左到右依次去写. // 例如, 13112345678 // 分成三部分: // 第一部分: 1 表示手机号码只能以 1 开头, 第一个位置, 写 1 或者 [1], 方括号没必要写了, 直接删掉即可 // 第二部分: [3-9] 表示手机号码第二位只能是 3-9 之间的 // 第三部分: \\d{9} 表示任意数字可以出现 9 次, 也只能出现 9 次 System.out.println("--------------- 验证手机号码 ---------------"); String regex1 = "1[3-9]\\d{9}"; System.out.println("13112345678".matches(regex1)); // true System.out.println("13712345667".matches(regex1)); // true System.out.println("13945679027".matches(regex1)); // true System.out.println("139456790271".matches(regex1)); // false // 座机电话号码 // 020-2324242 02122442 027-42424 0712-3242434 // 思路: // 在书写座机号正则的时候需要把正确的数据分为三部分 // 一: 区号 0\\d{2,3} // 0: 区号一定是以 0 开头的 // \\d{2,3}: 表示区号从第二位开始可以是任意的数字, 可以出现 2 到 3 次. // 二: - ? 表示次数, 0 次或一次 // 三: 号码 号码的第一位也不能以 0 开头, 从第二位开始可以是任意的数字, 号码的总长度: 5-10 位 System.out.println("--------------- 验证座机电话号码 ---------------"); String regex2 = "0\\d{2,3}-?[1-9]\\d{4,9}"; System.out.println("020-2324242".matches(regex2)); System.out.println("02122442".matches(regex2)); System.out.println("027-42424".matches(regex2)); System.out.println("0712-3242434".matches(regex2)); // 邮箱号码 // 3232323@qq.com zhangsan@itcast.cnn dlei0009@163.com dlei0009@pci.com.cn // 思路: // 在书写邮箱号码正则的时候需要把正确的数据分为三部分 // 第一部分: @ 的左边 \\w+, 表示任意的字母数字下划线, 至少出现一次就可以了 // 第二部分: @ 只能出现一次 // 第三部分: 还要分成三小段来看, 分别是 . 的前面, . 和 . 的后面三个部分 // 3.1 . 的左边 [\\w&&[^_]]{2,6}, 表示任意的字母加数字, 总共出现 2-6 次 (此时不能出现下划线) // 3.2 . 要写为 \\. 单独的一个 . 表示匹配任意的字符, 必须转义这个 . // 3.3 大写字母, 小写字母都可以, 只能出现 2-3 次 [a-zA-Z]{2,3} // 我们可以把 3.2 和 3.3 看成一组, 这一组可以出现 1 次或者两次, 用 () 括起来表示分组 System.out.println("--------------- 验证邮箱号码 ---------------"); String regex3 = "\\w+@[\\w&&[^_]]{2,6}(\\.[a-zA-Z]{2,3}){1,2}"; System.out.println("3232323@qq.com".matches(regex3)); System.out.println("zhangsan@itcast.cnn".matches(regex3)); System.out.println("dlei0009@163.com".matches(regex3)); System.out.println("dlei0009@pci.com.cn".matches(regex3)); // 24 小时的正则表达式 System.out.println("--------------- 24 小时 ---------------"); String regex4 = "([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d"; System.out.println("23:11:11".matches(regex4)); // 23:11:11 // 表示小时的部分: // 01 02 03 ... 09 // 10 11 12 ... 19 // 20 21 22 23 // | 前面的正则表达式匹配前两种情况, 后面的正则表达式匹配最后一种情况 // 分钟和秒钟的格式一样, 可以括起来当成一组, 再重复两次 String regex5 = "([01]\\d|2[0-3])(:[0-5]\\d){2}"; System.out.println("23:11:11".matches(regex5)); } }
"([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d"
中的 ([01]\\d|2[0-3])
中的 |
表示或者, |
前面的正则表达式或者后面的正则表达式, 只需要满足一个就行.
将需要作为 | 两侧部分的内容用小括号括起来.
"a((?i)b)c"
: 只忽略 b 的大小写, a 和 c 完全一样.
程序示例:
public class RegexDemo5 { public static void main(String[] args) { /* * 正则表达式练习: * 需求 * 请编写正则表达式验证用户名是否满足要求. 要求: 大小写字母, 数字, 下划线一共 4-16 位 * 请编写正则表达式验证身份证号码是否满足要求. * 简单要求: 18 位, 前 17 位任意数字, 最后一位可以是数字可以是大写或小写的 x 复杂要求: 按照身份证号码的格式严格要求. * * 身份证号码: * 41080119930228457x * 510801197609022309 * 15040119810705387X * 130133197204039024 * 430102197606046442 */ // 用户名要求:大小写字母, 数字, 下划线一共4-16位 String regex1 = "\\w{4,16}"; System.out.println("zhangsan".matches(regex1)); System.out.println("lisi".matches(regex1)); System.out.println("wangwu".matches(regex1)); System.out.println("$123".matches(regex1)); System.out.println("------------------------------"); // 身份证号码的简单校验: // 18 位, 前 17 位任意数字, 最后一位可以是数字可以是大写或小写的 x // 身份证号第一位不能是 0 String regex2 = "[1-9]\\d{16}(\\d|x|x)"; // (\\d|x|x) 两边的 () 必须要有, 表示参与 | 运算的范围 String regex3 = "[1-9]\\d{16}[\\dXx]"; // 放在方括号里面也可以表示或者, 此时不要再加上 |, [] 表示里面的内容任意出现一个就可以了 // 忽略 x 的大小写 String regex5 = "[1-9]\\d{16}(\\d(?i)x)"; System.out.println("41080119930228457x".matches(regex3)); System.out.println("510801197609022309".matches(regex3)); System.out.println("15040119810705387X".matches(regex3)); System.out.println("130133197204039024".matches(regex3)); System.out.println("430102197606046442".matches(regex3)); // 忽略大小写的书写方式 // 在匹配的时候忽略大小写 String regex4 = "a((?i)b)c"; System.out.println("------------------------------"); System.out.println("abc".matches(regex4)); // true System.out.println("ABC".matches(regex4)); // false System.out.println("aBc".matches(regex4)); // true // 身份证号码的严格校验 // 编写正则的心得: // 第一步: 按照正确的数据进行拆分 // 第二步: 找每一部分的规律, 并编写正则表达式 // 第三步: 把每一部分的正则拼接在一起, 就是最终的结果 // 书写的时候: 从左到右去书写. // 410801 1993 02 28 457x // 前面 6 位: 省份, 市区, 派出所等信息, 第一位不能是 0, 后面 5 位是任意数字 [1-9]\\d{5} // 年的前半段: 18 19 20 (18|19|20) // 年的后半段: 任意数字出现两次 \\d{2} // 月份: 01~09 10 11 12 (0[1-9]|1[0-2]) // 日期: 01~09 10~19 20~29 30 31 (0[1-9]|[12]\\d|3[01]) 日期分三种情况 // 后面四位: 任意数字出现 3 次 最后一位可以是数字也可以是大写 X 或者小写 x \\d{3}[\\dXx] String regex6 = "[1-9]\\d{5}(18|19|20)\\d{2}(@[1-9]|1[0-2])(@[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]"; System.out.println("------------------------------"); System.out.println("41080119930228457x".matches(regex6)); System.out.println("510801197609022309".matches(regex6)); System.out.println("15040119810705387X".matches(regex6)); System.out.println("130133197204039024".matches(regex6)); System.out.println("430102197606046442".matches(regex6)); } }


() 表示分组, a(bc) 表示 bc 作为整体出现.
. 不能匹配 \n.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)