正则表达式
介绍
什么是正则表达式
也叫做规则表达式。
是对字符串操作的一种逻辑公式。
事先定义好的一些特定字符串、以及这些特定字符的组合。
本质上就是一种过滤逻辑。
是一种文本模式。
特点
- 灵活性、逻辑性和功能性非常强。
- 可以迅速用极其简单的方式达到字符串的复杂控制。
- 初学者比较吃力。
编写规则
基本书写符号
符号 | 描述 |
---|---|
\ | 转义符 |
[ ] | 可接收的字符列表 |
[ ^ ] | 不接收的字符列表 |
| | 匹配“|”之前或之后的表达式 |
() | 将子表达式分组 |
- | 连字符 |
元字符
符号 | 描述 |
---|---|
. | 匹配除了换行符以外的任意一个字符 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
\d | 匹配一个数字,是[0-9] 的简写 |
\D | 匹配一个非数字,是[^0-9] 的简写 |
\s | 匹配一个空格,是[ \t\n\x0b\r\\f ] 的简写 |
\S | 匹配一个非空格 |
\w | 匹配一个单词字符(大小写字母、数字、下划线),是[ a-zA-Z_0-9] 的简写 |
\W | 匹配一个非单词字符(非大小写字母、数字、下划线外的字符),等同于[ ^\w] |
限定符
符号 | 描述 |
---|---|
* | 匹配>=0个,是{0,} 的简写 |
+ | 匹配>=1个,是{1,} 的简写 |
? | 匹配0个或1个,是{0,1} 的简写 |
{x} | 仅匹配x 个字符 |
{x,y} | 匹配>=x 且<=y 个字符 |
*? | 如果?是限定符* 或+ 或? 或{} 后面的第一个字符,则表示非贪婪模式(尽可能少的匹配字符),不是默认的贪婪模式 |
常用的正则表达式
- 校验数字
正则表达式 | 说明 |
---|---|
^[0-9]*$ | 数字 |
^\d{n}$ | n位的数字 |
^\d{n,}$ | 至少n位的数字 |
^\d{n,m}$ | n到m位的数字 |
^([1-9][0-9]*)+(.[0-9]{1,2})?$ | 非零开头的最多带两位小数的数字 |
^(-)?\d+(.\d{1,2})?$ | 带1-2位小数的正数或负数 |
^[0-9]+(.[0-9]{1,3})?$ | 有1-3位小数的正实数 |
^\d+$ | 非负整数 |
^((-+d)?(0+))$ | 非正整数 |
- 校验字符串
说明 | 正则表达式 |
---|---|
汉字 | ^ [\u4e00-\u9fa5]{0,}$ |
英文和数字 | ^ [A-Za-z0-9]+$ |
长度为3-20的所有字符 | ^.{3,20}$ |
由26个英文字母组成的字符串 | ^ [A-Za-z]+$ |
由数字、26个英文字母或者下划线组成的字符串 | ^\w+$ 或 ^\w{3,20}$ |
中文、英文、数字包括下划线 | ^ [\u4E00-\u9FA5A-Za-z0-9_]+$ |
中文、英文、数字但不包括下划线等符号 | ^ [\u4E00-\u9FA5A-Za-z0-9]+$ |
可以输入含有^%&’,;=?$"等字符 | [^%&’,;=?$\x22]+ |
禁止输入含有~的字符 | [^~\x22]+ |
- 其他常用
正则表达式 | 说明 |
---|---|
^1[0-9]{10}$ | 验证1开头的11位手机号 |
^1[3|4|5|7|8][0-9]{9}$ | 精确验证目前发行的11位手机号 |
^(0[0-9]{2,3}/-)?([2-9][0-9]{6,7})$ | 座机电话:区号+座机号码 |
^(0[0-9]{2,3}/-)?([2-9][0-9]{6,7})+(/-[0-9]{1,4})?$ | 座机电话:区号+座机号码+分机号码 |
^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$ | 身份证号 |
Pattern类和Matcher类
java正则表达式通过java.util.regex包下的Pattern类与Matcher类实现
Pattern类
Pattern用于创建一个正则表达式,也可以说是创建一个匹配模式,它的构造方法是私有的不可以直接创建,可以通过Pattern.compile(String regex)简单工厂方法创建一个正则表达式。
做一些简单的匹配操作。
Pattern p = Pattern.compile("\\w+");
System.out.println(p.pattern());//\w+
//pattern()方法返回正则表达式的字符串形式,就是返回Pattern.compile(String regex)的regex参数。
- Pattern.split(CharSequence input)
用于分割字符串,返回一个string类型的数组。
Pattern p = Pattern.compile("\\d+");
String[] s = p.split("我的QQ是:456456我的电话是:0532214我的邮箱是:aaa@aaa.com");
for (int i = 0; i < s.length; i++) {
System.out.println(s[i]);
/*运行结果位:
我的QQ是:
我的电话是:
我的邮箱是:aaa@aaa.com*/
}
- Pattern.matches(String regex,CharSequence input)
是一个静态方法。
用于快速匹配字符串。
适用于只匹配一次,且匹配全部字符串。
System.out.println(Pattern.matches("\\d+", "1234"));//true,匹配到所有字符串
System.out.println(Pattern.matches("\\d+", "1234abc"));//false,sbc不能匹配到
System.out.println(Pattern.matches("\\d+", "12abc34"));//false,sbc不能匹配到
System.out.println(Pattern.matches("\\d+", "abc1234"));//false,sbc不能匹配到
//这两种方式的作用效果等价
System.out.println(Pattern.matches("\\d+", "123"));//true
System.out.println(Pattern.compile("\\d+").matcher("123").matches());//true
Matcher类
Pattern.Matcher(CharSequence input)返回一个Matcher对象。
构造方法是私有的,不能随意创建,只能通过Pattern.Matcher(CharSequence input)方法得到该类的实例对象。
提供了对正则表达式的分组支持。
提供了对正则表达式的都次匹配支持。
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("12abc34");
System.out.println(m.pattern());//\d+ 返回的是具体的正则表达式
- Matcher.matches()
对整个字符串匹配,整个字符串都匹配返回true,否则返回false。
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("12abc34");
System.out.println(m.matches());//false abc不能被\d+匹配
Matcher m2 = p.matcher("1234");
System.out.println(m2.matches());//true
- Matcher.lookingAt()
匹配开头的字符串,匹配到返回true,匹配不到返回false。
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("123abc45");
System.out.println(m.lookingAt());//true
Matcher m1 = p.matcher("123abc");
System.out.println(m1.lookingAt());//true
Matcher m2 = p.matcher("abc123");
System.out.println(m2.lookingAt());//false 字符串开头不匹配\d+
- Matcher.find()
只要满足存在匹配的就返回true,否则返回false。
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("1234abc");
Matcher m1 = p.matcher("12abc34");
Matcher m2 = p.matcher("abc1234");
System.out.println(m.find());//true
System.out.println(m1.find());//true
System.out.println(m2.find());//true
- 执行了matches()或lookingAt()或find()匹配操作后,返回true,可以使用的方法。
- matcher.start():返回匹配到的子字符串的开头字符在字符串中的索引位置。
- matcher.end():执行了matches()或lookingAt()或find()匹配操作后,返回true,可以使用这个方法。
- matcher.group():执行了matches()或lookingAt()或find()匹配操作后,返回true,可以使用这个方法。
- matcher.groupCount():执行了matches()或lookingAt()或find()匹配操作后,返回true,可以使用这个方法。
Pattern p1 = Pattern.compile("\\d+");//创建正则表达式
Matcher m1 = p1.matcher("abc1234aa");//创建Matcher对象
System.out.println(m1.find());//true 字符串中是否存在满足匹配的条件
System.out.println(m1.start());//3 子字符串的首个字符在字符串中的索引
System.out.println(m1.end());//7 子字符串最后一个字符后边的字符在字符串中的索引
System.out.println(m1.group());//1234 匹配的分组
System.out.println(m1.groupCount());//0 分组的数量
Matcher m2 = p1.matcher("1234");//创建一个Matcher对象
System.out.println(m2.matches());//true 字符串中是否全部满足匹配条件
System.out.println(m2.start());//0 子字符串的首个字符在字符串中的索引
System.out.println(m2.end());//4 子字符串最后一个字符后边的字符在字符串中的索引
System.out.println(m2.group());//1234 匹配的分组
System.out.println(m2.groupCount());//0 分组的数量
Matcher m3 = p1.matcher("1234aa");//创建一个Matcher对象
System.out.println(m3.lookingAt());//true 字符串的开头是否满足匹配条件
System.out.println(m3.start());//0 子字符串的首个字符在字符串中的索引
System.out.println(m3.end());//4 子字符串最后一个字符后边的字符在字符串中的索引
System.out.println(m3.group());//1234 匹配的分组
System.out.println(m3.groupCount());//0分组的数量
Pattern c = Pattern.compile("(\\d+)([a-z]+)");//创建一个正则表达式(两个分组)
Matcher m4 = c.matcher("abc123dd");//创建一个matcher对象
System.out.println(m4.find());//true 字符串中是否存在满足匹配的条件
System.out.println(m4.start(1));//3 第一个分组的子字符串首字符在字符串中的索引
System.out.println(m4.start(2));//6 第二个分组的子字符串首字符在字符串中的索引
System.out.println(m4.end(1));//6 第一个分组的子字符串最后一个字符后边的字符在字符串中的索引
System.out.println(m4.end(2));//8 第二个分组的子字符串最后一个字符后边的字符在字符串中的索引
System.out.println(m4.group(1));//123 匹配的第一个分组的字符串的内容
System.out.println(m4.group(2));//dd 匹配的第二个分组的字符串的内容
System.out.println(m4.groupCount());//2 返回的是分组的数量
Matcher m5 = c.matcher("123dd");//创建一个Matcher对象
System.out.println(m5.lookingAt());//true 字符串的开头是否满足匹配条件
System.out.println(m5.start(1));//0 第一个分组的子字符串首字符在字符串中的索引
System.out.println(m5.start(2));//3 第二个分组的子字符串首字符在字符串中的索引
System.out.println(m5.end(1));//3 第一个分组的子字符串最后一个字符后边的字符在字符串中的索引
System.out.println(m5.end(2));//5 第二个分组的子字符串最后一个字符后边的字符在字符串中的索引
System.out.println(m5.group(1));//123 匹配的第一个分组的字符串的内容
System.out.println(m5.group(2));//dd 匹配的第二个分组的字符串的内容
System.out.println(m5.groupCount());//2 返回的是分组的数量
Matcher m6 = c.matcher("123abc");
System.out.println(m6.matches());//true 字符串的开头是否满足匹配条件
System.out.println(m6.start(1));//0 第一个分组的子字符串首字符在字符串中的索引
System.out.println(m6.start(2));//3 第二个分组的子字符串首字符在字符串中的索引
System.out.println(m6.end(1));//3 第一个分组的子字符串最后一个字符后边的字符在字符串中的索引
System.out.println(m6.end(2));//6 第二个分组的子字符串最后一个字符后边的字符在字符串中的索引
System.out.println(m6.group(1));//123 匹配的第一个分组的字符串的内容
System.out.println(m6.group(2));//abc 匹配的第二个分组的字符串的内容
System.out.println(m6.groupCount());//2 返回的是分组的数量
注意: 当执行Matcher对象的start()、end()方法、group()方法、groupCount()方法时,前提时已经执行了Matcher对象的matches()方法 或 find()方法 或 lookingAt()方法,否则运行报错:
参考地址:
https://segmentfault.com/a/1190000009162306
https://blog.csdn.net/weixin_44259720/article/details/88179885
https://www.cnblogs.com/ggjucheng/p/3423731.html