Java学习之正则表达式篇
文章目录
- 快速入门
- 正则表达式基本语法
- 1. 字符匹配符
- 2. 选择匹配符
- 3. 限定符
- 4. 定位符
- 5. 分组组合 、反向引用符
- 6.特殊字符
- 三个常用类
- Pattern
- Matcher
- PatternSyntaxException
- 反向引用
- 原理
- 应用实例
快速入门
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*** @Author: mei_ming* @DateTime: 2022/6/4 16:25* @Description: 体验正则表达式*/
public class Regexp_ {@Testpublic void test1(){// String content="2000年5月,JDK1.3、JDK1.4和J2SE1.3相继发布," +
// "几周后其获得了Apple公司Mac OS X的工业标准的支持。2001年9月24日," +
// "J2EE1.3发布。2002年2月26日,J2SE1.4发布。自此Java的计算能力有了大幅提升" +
// ",与J2SE1.3相比,其多了近62%的类和接口。在这些新特性当中,还提供了广泛的XML支持、" +
// "安全套接字(Socket)支持(通过SSL与TLS协议)、全新的I/OAPI、正则表达式、日志与断言。" +
// "2004年9月30日,J2SE1.5发布,成为Java语言发展史上的又一里程碑。为了表示该版本的重要性," +
// "J2SE 1.5更名为Java SE 5.0(内部版本号1.5.0),代号为“Tiger”,Tiger包含了从1996年发布" +
// "1.0版本以来的最重大的更新,其中包括泛型支持、基本类型的自动装箱、改进的循环、枚举类型、格式化I/O及可变参数。";//百度热搜 代码简化后String content ="<div class=\"FYB_RD\"><div class=\"cr-title c-gap-bottom-xsmall\" " +"data-click=\"true\" title=\"百度热搜\"><a class=\"c-color-t opr-toplist1-title_1LgpS\" " +"<a target=\"_blank\" title=\"考生:3年的数学难题都在卷子里\" href=\"https://top.baidu.co" +"<a target=\"_blank\" title=\"湖北考生请枪手代答?当地辟谣\" href=\"/s?wd=%E6%B9%96%E5%8C%97%E8%80%83" +"<a target=\"_blank\" title=\"成都考生提前一小时答完数学题\" href=\"/s?wd=%E6%88%90%E9%83%BD%E8%8";//提取文章中的所有的英文单词//(1) 传统方法,使用遍历方式,代码量大,效率不高//(2) 正则表达式//1. 创建Pattern对象,//提取文章中的所有的英文单词//Pattern pattern = Pattern.compile("[a-zA-Z]+");//提取文章中的所有的数字//Pattern pattern = Pattern.compile("[0-9]+");//提取文章中的所有的英文单词和数字//Pattern pattern = Pattern.compile("([a-zA-Z]+)|([0-9]+)");//提取百度热搜的标题Pattern pattern = Pattern.compile("<a target=\"_blank\" title=\"(\\S*)\"");//2. 创建匹配器对象// 理解 matcher 匹配器按照pattern模式对象,到content文本中去匹配// 找到则返回true, 否则返回falseMatcher matcher = pattern.matcher(content);//3. 可以开始循环匹配while(matcher.find()){//匹配内容,文本,放到 matcher.group(0)System.out.println("找到:" + matcher.group(1));}}
}
学习正则表达式可以快速验证邮箱格式、手机格式等
正则表达式是对字符串执行模式匹配的技术
正则表达式基本语法
从功能上看,共有六大类元字符
转义号 \
\ 符号说明:在我们使用正则表达式去检索某些特殊字符的时候,需要用到转义符号,否则检索不到结果。如下所示:
import org.junit.Test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** @Author: mei_ming* @DateTime: 2022/6/8 22:29* @Description: 演示转义符号的使用*/
public class Regexp_02 {@Testpublic void test() {String content = "abc()def.123(";//匹配 ( => \\(//匹配 . => \\.Pattern pattern = Pattern.compile("\\.");//2. 创建匹配器对象// 理解 matcher 匹配器按照pattern模式对象,到content文本中去匹配// 找到则返回true, 否则返回falseMatcher matcher = pattern.matcher(content);//3. 可以开始循环匹配while (matcher.find()) {//匹配内容,文本,放到 matcher.group(0)System.out.println("找到:" + matcher.group(0));}}
}
1. 字符匹配符
符号 | 含义 | 示例 | 解释 |
---|---|---|---|
[ ] | 可接收的字符列表 | [efgh] | e/f/g/h 中的任何一个字符 |
[^] | 不接收的字符列表 | [^abc] | 除 a、b、c之外的任意一个字符,包括数字和特殊符号 |
- | 连字符 | A-Z | 任意单个大写字母 |
. | 匹配除\n以外的任何字符 | a…b | 以a开头,以b结尾,中间2个任意 如 aabb,aa1b,a23b,a#%b |
\\d | 匹配单个数字字符,等价于[0-9] | \\d{3}(\\d)? | 包含3个、4个数字的字符串 如 123,1234 |
\\D | 匹配单个非数字字符,等价于[^0-9] | \\D(\\d)* | 以非数字开头,后接任意个数字字符串 如 a123,a |
\\w | 匹配单个数字、大小写字母字符、下划线,等价于[0-9a-zA-Z_] | \\d{3}\\w{4} | 以3个数字开头,长度为7的数字字符串 如 123abcd,12345PR |
\\W | 匹配单个非数字、大小写字母字符,等价于[^0-9a-zA-Z_] | \\W+\\d{2} | 以至少1个非数字字母字符开头,2个数字结尾的字符串 如 #12,#A#12 |
\\s | 匹配任何空白字符(空格、制表符) | ||
\\S | 匹配任何非空白字符,与\\s相反 |
示例代码:
import org.junit.Test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Regexp_03 {@Testpublic void test() {String content = "abcdefABC. 123(";//String regStr= "[a-z]"; //匹配 a-z之间的任意一个字符//String regStr= "[^a-z]"; //匹配 不在a-z之间的任意一个字符//String regStr= "abc"; //匹配 abc 默认区分大小写//(?i)abc 表示 abc 都不区分大小写//a(?i)bc 表示 bc 不区分大小写//a((?i)b)c 表示只有 b 不区分大小写//还可以写 Pattern pattern = Pattern.compile(regStr,Pattern.CASE_INSENSITIVE); 设置不区分//String regStr = "(?i)abc";//String regStr = "[A-Z]"; //匹配 A-Z 之间的任意一个字符//String regStr = "[^A-Z]"; //匹配 不在A-Z 之间的任意一个字符//String regStr = "[0-9]"; //匹配 0-9 之间的任意一个字符//String regStr = "[^0-9]"; //匹配 不在0-9 之间的任意一个字符//String regStr = "\\s"; //匹配空格,制表符String regStr = "\\S"; //匹配非空格,非制表符Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);while (matcher.find()) {System.out.println("找到:" + matcher.group(0));}}
}
2. 选择匹配符
符号 | 含义 | 示例 | 解释 |
---|---|---|---|
| | 匹配’|'之前或之后的表达式 | ab|bc | ab或者bc |
import org.junit.Test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*** @Author: mei_ming* @DateTime: 2022/6/9 7:22* @Description: 选择匹配符*/
public class Regexp_04 {@Testpublic void test() {String content = "abcdacdv";String regStr = "ab|cd"; //Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);while (matcher.find()) {System.out.println("找到:" + matcher.group(0));}}
}
3. 限定符
符号 | 含义 | 示例 | 解释 |
---|---|---|---|
* | 指定字符重复0次或n次 | (abc)* | 仅包含任意个abc的字符 如 abc、abcabcabc |
+ | 指定字符重复1次或n次 | m+(abc)* | 以至少1个m开头,后接任意个abc的字符 如 m、mabc、mabcabcabc |
? | 指定字符重复0次或1次 | m+abc? | 以至少1个m开头,后接ab或abc的字符串 如mab、mabc、mmab、mmabc |
{n} | 只能输入n个字符 | [abcd]{3} | 由abcd中的字母组成的任意长度为3的字符串 如abc、adc、acd |
{n,} | 指定至少n个字符 | [abcd]{3,} | 由abcd中的字母组成的任意长度不小于3的字符串 如abc、adcc、acdasc |
{n,m} | 指定至少n个但不多于m个字符 | [abcd]{3,5} | 由abcd中的字母组成的任意长度不小于3,不大于5的字符串 如abc、adcc、acdas |
import org.junit.Test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** @Author: mei_ming* @DateTime: 2022/6/9 7:22* @Description: 限定符*/
public class Regexp_05 {@Testpublic void test() {String content = "a1111111aaaaa";//a{3},1{4},\\d{2}//String regStr = "a{3}"; // 匹配 aaa//String regStr = "1{4}"; // 匹配 1111//String regStr = "\\d{2}"; // 匹配 11、11、11 任意两个数字//a{3,4},1{4,5},\\d{2,5}//细节:java匹配默认贪婪匹配,尽可能匹配多的//String regStr="a{3,4}"; //理论上匹配 aaa 或 aaaa ,实际匹配 aaaa//String regStr="1{4,5}"; //理论上匹配 1111 或 11111 ,实际匹配 11111//String regStr="\\d{2,5}"; //理论上匹配 2位,3位,4位,5位数字 ,实际匹配 11111,11//1+//String regStr="1+"; //理论上匹配 1个1或n个1 ,实际匹配 1111111 ,符合贪婪匹配//String regStr="\\d+"; //理论上匹配 1个数字或n个数字 ,实际匹配 1111111//1*//String regStr="1*"; //理论上匹配 0个1或n个1//?String regStr="a1?"; //理论上匹配 a 或 a1Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);while (matcher.find()) {System.out.println("找到:" + matcher.group(0));}}
}
4. 定位符
符号 | 含义 | 示例 | 解释 |
---|---|---|---|
^ | 指定起始字符 | ^[0-9]+[a-z]* | 以至少1个数字开头,后接任意个小写字母的字符 如123,123a |
$ | 指定结束字符 | ^[0-9]+\\-[a-z]+$ | 以至少1个数字开头,后接- 再加上至少1个小写字母的字符 如 123-abc |
\\b | 匹配目标字符串的边界 | ma\\b | maenma ma 会匹配第二、三个ma |
\\B | 匹配目标字符串的非边界 | ma\\B | 与\\b相反 maenma ma 会匹配第一个ma |
{n,} | 指定至少n个字符 | [abcd]{3,} | 由abcd中的字母组成的任意长度不小于3的字符串 如abc、adcc、acdasc |
{n,m} | 指定至少n个但不多于m个字符 | [abcd]{3,5} | 由abcd中的字母组成的任意长度不小于3,不大于5的字符串 如abc、adcc、acdas |
import org.junit.Test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*** @Author: mei_ming* @DateTime: 2022/6/9 7:22* @Description: 定位符*/
public class Regexp_06 {@Testpublic void test() {String content = "123-abc";//以至少1个数字开头,至少一个小写字母结束的字符串String regStr="^[0-9]+\\-[a-z]+$";Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);while (matcher.find()) {System.out.println("找到:" + matcher.group(0));}}@Testpublic void test2(){String content = "maenming enma enmingma";//表示匹配边界的ma[这里的边界是指:被匹配的字符串最后, 也可以是空格的子字符串的后面]//String regStr="ma\\b"; //找到后两个ma// \\B 与 \\b相反String regStr="ma\\B"; //找到第一个maPattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);while (matcher.find()) {System.out.println("找到:" + matcher.group(0));}}
}
5. 分组组合 、反向引用符
- 常用分组
常用分组构造形式 | 说明 |
---|---|
(pattern) | 非命名捕获。捕获匹配的子字符串。编号为0的第一个捕获是由整个正则表达式模式匹配的文本,其他捕获结果则根据左括号的顺序从1开始自动编号 |
(?<name>pattern) | 命名捕获。捕获匹配的子字符串。匹配的分组可以按照名字来访问也可以按照编号 |
import org.junit.Test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*** @Author: mei_ming* @DateTime: 2022/6/9 7:22* @Description: 捕获分组*/
public class Regexp_07 {@Testpublic void test() {String content = "1234abcd2234";//matcher.group(0) 存放匹配到的全部子串//matcher.group(1) 存放第一个分组//......String regStr="(\\d\\d)(\\d)(\\d)";Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);while (matcher.find()) {System.out.println("找到:" + matcher.group(0));System.out.println("第1个分组:"+matcher.group(1));System.out.println("第2个分组:"+matcher.group(2));System.out.println("第3个分组:"+matcher.group(3));}}@Testpublic void test2(){String content = "1234abcd2234";//matcher.group(0) 存放匹配到的全部子串//matcher.group(1) 存放第一个分组//......//还可以按照matcher.group("g1") 获取分组String regStr="(?<g1>\\d\\d)(?<g2>\\d\\d)";Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);while (matcher.find()) {System.out.println("找到:" + matcher.group(0));System.out.println("分组1:" + matcher.group(1));System.out.println("分组1(name):" + matcher.group("g1"));System.out.println("分组2:" + matcher.group(2));System.out.println("分组2(name):" + matcher.group("g2"));}}
}
- 特殊分组(不能按group(编号) 取值)
常用分组构造形式 | 说明 |
---|---|
(?:pattern) | 匹配pattern但不捕获该匹配的子表达式,即他是一个非捕获匹配 ,如 industr(?:y|ies) 等价于 industry|industries |
(?=pattern) | 一个非捕获匹配 ,如 windows(?=95|98|2000) 匹配的是 windows 2000 的windows 而不匹配windows 3.1的windows |
(?!pattern) | 一个非捕获匹配 ,如 windows(?!95|98|2000) 匹配的是 windows 3.1 的windows 而不匹配windows 2000的windows |
import org.junit.Test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** @Author: mei_ming* @DateTime: 2022/6/9 7:22* @Description: 非捕获分组*/
public class Regexp_08 {//(?: )@Testpublic void test() {String content = "hi小明同学 hi小李同学 hi小黄同学";//String regStr="小明同学|小李同学|小黄同学";//等价于String regStr="小(?:明|李|黄)同学";//不能捕获 matcher.group(1)Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);while (matcher.find()) {System.out.println("找到:" + matcher.group(0));}}//(?= )@Testpublic void test2() {String content = "hi同学小明 hi同学小李 hi同学小黄";String regStr="同学(?=小明|小李)";//匹配到的是小明or小李 的 "同学"Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);while (matcher.find()) {System.out.println("找到:" + matcher.group(0));}}//(?! )@Testpublic void test3() {String content = "hi同学小明 hi同学小李 hi同学小黄";String regStr="同学(?!小明|小李)";//匹配到的不是小明or小李 的 "同学"Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);while (matcher.find()) {System.out.println("找到:" + matcher.group(0));}}
}
非贪婪匹配
:
import org.junit.Test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*** @Author: mei_ming* @DateTime: 2022/6/9* @Description: 非贪婪匹配*/
public class Regexp_09 {//(?: )@Testpublic void test() {String content = "a11111111aaa";//String regStr="\\d+";//默认贪婪匹配 返回 11111111String regStr="\\d+?"; //非贪婪匹配 返回 1,1,1,1,1,1,1,1Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);while (matcher.find()) {System.out.println("找到:" + matcher.group(0));}}
}
6.特殊字符
略
三个常用类
java.util.regex 包下主要包括3个类 Pattern 、Matcher、PatternSyntaxException
Pattern
pattern对象是一个正则表达式对象。Pattern类没有公共构造方法。要创建一个Pattern对象,调用其公共静态方法,返回一个Pattern对象,该方法接受一个正则表达式作为它的第一个参数,比如:Pattern pattern = Pattern.compile(String regex)。
import org.junit.Test;
import java.util.regex.Pattern;/*** @Author: mei_ming* @DateTime: 2022/6/11 10:38* @Description: 演示matches方法,用于整体匹配,在验证输入的字符串是否满足条件使用,用于简化开发*/
public class PatternMethod {@Testpublic void test(){String content = "hello world";//String regStr="hello"; //falseString regStr = "hello.*"; //trueboolean matches = Pattern.matches(regStr, content);System.out.println("整体匹配= "+matches);}
}
Matcher
Matcher 对象是对输入字符串进行解释和匹配的引擎。与Pattern类一样,Matcher也没有公共构造方法。你需要调用Pattern对象的matcher()返回一个Matcher对象。
import org.junit.Test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*** @Author: mei_ming* @DateTime: 2022/6/11 13:44* @Description: Matcher中的方法*/
public class MatcherMethod {@Testpublic void test(){String content = "hello world ,hello mei_ming";String regStr="hello";Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);while (matcher.find()) {System.out.println("------------------");System.out.println("起始位置:"+matcher.start());System.out.println("结束位置:"+matcher.end());System.out.println("找到:" + matcher.group(0));System.out.println("找到:"+content.substring(matcher.start(),matcher.end())); //等同于 group(0)}}//整体匹配@Testpublic void test2(){String content = "hello world ,hello mei_ming";String regStr="hello.*";Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);//整体匹配System.out.println(matcher.matches()); //true}//替换@Testpublic void test3(){String content = "hello world ,hello mei_ming";//替换成regStr的值String regStr="hello";Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);String newContent = matcher.replaceAll("hi");System.out.println("返回的字符串:"+newContent);System.out.println("原来的字符串:"+content);}
}
PatternSyntaxException
PatternSyntaxException是一个非强制异常类,他表示一个正则表达式模式中的语法错误
反向引用
- 分组:用圆括号组成一个比较复杂的匹配模式,称为一个分组或一个子表达式
- 捕获:把正则表达式中的分组内容,保存到内存中以数字编号或显式命名的组里,方便后面引用,从左向右,以分组的左括号为标志,第一个出现分组为1…,整体分组为0
- 反向引用:圆括号的内容被捕获后,可以在这个括号后被使用,从而写出一个比较实用的匹配模式,成为反向引用,内部反向引用 \\分组号 ,外部反向引用: $分组号
import org.junit.Test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*** @Author: mei_ming* @DateTime: 2022/6/11 14:05* @Description: 反向引用*/
public class Regexp_11 {@Testpublic void test(){String content = "abc1221 33abcd144444acbc 5566 ";//匹配两个连续相同的数//String regStr = "(\\d)\\1";//匹配五个连续相同的数//String regStr = "(\\d)\\1{4}";//匹配abba这样的四位数String regStr = "(\\d)(\\d)\\2\\1";Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);while (matcher.find()) {System.out.println("找到:" + matcher.group(0));}}@Testpublic void test2(){String content = "12345-333999666";//匹配 12345-333999666 这样的数 -左边5位数随机 -右边9位数 aaabbbcccString regStr = "\\d{5}-(\\d)\\1{2}(\\d)\\2{2}(\\d)\\3{2}";Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);while (matcher.find()) {System.out.println("找到:" + matcher.group(0));}}
}
原理
import org.junit.Test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** @Author: mei_ming* @DateTime: 2022/6/8 20:59* @Description: 正则底层原理*/
public class RegTheory {//匹配无分组的情况@Testpublic void test1(){String content="2000年5月,JDK1.3、JDK1.4和J2SE1.3相继发布,几周后其获得了Apple公司Mac OS X的工业标准的支持。2001年9月24日," +"J2EE1.3发布。2002年2月26日,J2SE1.4发布。自此Java的计算能力有了大幅提升" +",与J2SE1.3相比,其多了近62%的类和接口。在这些新特性当中,还提供了广泛的XML支持、" +"安全套接字(Socket)支持(通过SSL与TLS协议)、全新的I/OAPI、正则表达式、日志与断言。" +"2004年9月30日,J2SE1.5发布,成为Java语言发展史上的又一里程碑。为了表示该版本的重要性," +"J2SE 1.5更名为Java SE 5.0(内部版本号1.5.0),代号为“Tiger”,Tiger包含了从1996年发布" +"1.0版本以来的最重大的更新,其中包括泛型支持、基本类型的自动装箱、改进的循环、枚举类型、格式化I/O及可变参数。";//1. 创建Pattern对象,//提取文章中的四个数字// \\d 表示一个任意的数字Pattern pattern = Pattern.compile("\\d\\d\\d\\d");//2. 创建匹配器对象// 理解 matcher 匹配器按照pattern模式对象,到content文本中去匹配// 找到则返回true, 否则返回falseMatcher matcher = pattern.matcher(content);//3. 可以开始循环匹配/*** matcher.find() 完成的任务* 1. 根据指定的规则,定位满足规则的子字符串(比如2000)* 2. 找到后,将 子字符串的开始索引记录到matcher对象属性 int[] groups; 中* 赋值 groups[0] = 0 即开始位置* groups[1] = 4 即子字符串结束位置 +1* 3. 同时记录oldLast的值为4,作为下一次执行find的位置** matcher.group(0) 完成的任务** 源码:* public String group(int group) {* if (first < 0)* throw new IllegalStateException("No match found");* if (group < 0 || group > groupCount())* throw new IndexOutOfBoundsException("No group " + group);* if ((groups[group*2] == -1) || (groups[group*2+1] == -1))* return null;* return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();* }** 1. getSubSequence 方法 返回从 groups[group * 2]到 groups[group * 2 + 1] 的子串 ,即group=0* 根据groups[0]=0,groups[1]=4 的记录的位置,从content开始截取子字符串* 就是[0,4)的位置上的字符** 若再次执行, groups[0] = 65 , groups[1] = 69 , ordLast = 69* getSubSequence(65,69) 返回 2001*/while(matcher.find()){//匹配内容,文本,放到 matcher.group(0)System.out.println("找到:" + matcher.group(0));}}//有分组的情况@Testpublic void test2(){String content="2000年5月,JDK1.3、JDK1.4和J2SE1.3相继发布,几周后其获得了Apple公司Mac OS X的工业标准的支持。2001年9月24日," +"J2EE1.3发布。2002年2月26日,J2SE1.4发布。自此Java的计算能力有了大幅提升" +",与J2SE1.3相比,其多了近62%的类和接口。在这些新特性当中,还提供了广泛的XML支持、" +"安全套接字(Socket)支持(通过SSL与TLS协议)、全新的I/OAPI、正则表达式、日志与断言。" +"2004年9月30日,J2SE1.5发布,成为Java语言发展史上的又一里程碑。为了表示该版本的重要性," +"J2SE 1.5更名为Java SE 5.0(内部版本号1.5.0),代号为“Tiger”,Tiger包含了从1996年发布" +"1.0版本以来的最重大的更新,其中包括泛型支持、基本类型的自动装箱、改进的循环、枚举类型、格式化I/O及可变参数。";//1. 创建Pattern对象,//提取文章中的四个数字// \\d 表示一个任意的数字Pattern pattern = Pattern.compile("(\\d\\d)(\\d\\d)");//2. 创建匹配器对象// 理解 matcher 匹配器按照pattern模式对象,到content文本中去匹配// 找到则返回true, 否则返回falseMatcher matcher = pattern.matcher(content);//3. 可以开始循环匹配/*** matcher.find() 完成的任务* 1. 根据指定的规则,定位满足规则的子字符串(比如2000)* 2. 找到后,将 子字符串的开始索引记录到matcher对象属性 int[] groups; 中* 2.1 赋值 groups[0] = 0 即开始位置* groups[1] = 4 即子字符串结束位置 +1** 2.2 接着赋值 groups[2]=0, groups[3]=2 记录第一个分组()匹配到的字符串* 2.3 接着赋值 groups[4]=2, groups[5]=4 记录第二个分组()匹配到的字符串** 3. 同时记录oldLast的值为4,作为下一次执行find的位置** matcher.group(0) 完成的任务** 源码:* public String group(int group) {* if (first < 0)* throw new IllegalStateException("No match found");* if (group < 0 || group > groupCount())* throw new IndexOutOfBoundsException("No group " + group);* if ((groups[group*2] == -1) || (groups[group*2+1] == -1))* return null;* return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();* }** 1. getSubSequence 方法 返回从 groups[group * 2]到 groups[group * 2 + 1] 的子串 ,* 若group=0时 ,根据groups[0]=0,groups[1]=4 的记录的位置,从content开始截取子字符串* 就是[0,4)的位置上的字符* 若group=1时 ,就是groups[2]=0,groups[3]=2 的记录的位置,也就是 [0,2)* 若group=2时 ,就是groups[4]=2,groups[5]=4 的记录的位置,也就是 [2,4)**/while(matcher.find()){//小结://1. 如果正则表达式有() 即 有分组//2. 取出字符串如下//3. group(0) : 取 匹配到的字符串//4. group(1) : 取 第一组的字符串//5. group(2) : 取 第二组的字符串//6. 越界则报错 throw new IndexOutOfBoundsException("No group " + group);System.out.println("找到:" + matcher.group(0));System.out.println(" 找到:" + matcher.group(1));System.out.println(" 找到:" + matcher.group(2));}}
}
应用实例
import org.junit.Test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** @Author: mei_ming* @DateTime: 2022/6/11 9:34* @Description: 正则表达式应用实例*/
public class Regexp_10 {@Testpublic void test(){//汉字//String content="中文汉字"; //满足要求//String regStr="^[\u0391-\uffe5]+$";//邮政编码//要求:是1-9开头的一个6位数//String content = "330324";//String regStr="^[1-9]\\d{5}$";// QQ号//要求:是1-9开头的一个5位-10位数//String content = "1791666142";//String regStr="^[1-9]\\d{4,9}$";// 手机号//要求:是以13,14,15,18 开头的11位数String content = "13916661421";String regStr="^1[3|4|5|8]\\d{9}$";Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);if(matcher.find()){System.out.println("满足要求");}else{System.out.println("不满足要求");}}@Testpublic void test2(){//URL验证//String content = "https://baike.baidu.com/item/Java/85979?fr=aladdin";String content = "http://tgxmf.yxaad.com/school/dl/9607/" +"?source=shyx-pc&plan=3wanglianyu-DL&unit=dlzhancheng%EF%BC%8Bjavaxiangmu&" +"keyword=javapeixunlingjichu&e_creative=58309754528&e_keywordid=393605165955&bd_vid=11917634435375433147";/*** 验证思路:* 1. 匹配开头:^((https?)://) 可以是 http:// | https://* 2. 然后通过 ([\w-]+\.)+[\w-]+ 匹配 baike.baidu.com* 3. (\/[\w-?=&/%.#]*)?$ 匹配 /item/Java/85979?fr=aladdin*/String regStr="^((https?)://)([\\w-]+\\.)+[\\w-]+(\\/[\\w-?=&/%.#]*)?$";Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);if(matcher.find()){System.out.println("满足要求");}else{System.out.println("不满足要求");}}//测试 [.]@Testpublic void test3(){String content = "hello.world";//String regStr="."; //匹配所有String regStr="[.]"; //匹配 .Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);while(matcher.find()){System.out.println("找到:"+matcher.group(0));}}//邮箱验证 //matches:整体匹配@Testpublic void test4(){//只有1个@//@前面是用户名,可以是a-zA-Z0-9_-字符//@后面是域名,比如sohu.com souhu.com.cnString content = "1791666142@qq.com";String regStr= "^[\\w-]+@([a-zA-Z]+\\.)+[a-zA-Z]+$";if(content.matches(regStr)){System.out.println("符合");}else{System.out.println("不符合");}}//判断数字@Testpublic void test5(){//1. 验证整数和浮点数//2. 正数和负数//+1 √//-1 √//0.1 √//12.21 √//23 √String content = "0.234";String regStr= "^[-+]?([1-9]\\d*|0)(\\.\\d+)?$";if(content.matches(regStr)){System.out.println("符合");}else{System.out.println("不符合");}}//验证URL 取协议、域名等@Testpublic void test6(){//协议、域名、端口、资源String content = "http://www.baidu.com:8080/admin/index.jsp";String regStr= "^([a-zA-Z]+)://([a-zA-Z.]+):(\\d+)[\\w-/]*/([\\w.]+)$";Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);if(matcher.find()){System.out.println("匹配成功:"+matcher.group(0));System.out.println("协议:"+matcher.group(1));System.out.println("域名:"+matcher.group(2));System.out.println("端口:"+matcher.group(3));System.out.println("资源:"+matcher.group(4));}else{System.out.println("不符合");}}
}
个人自学用笔记,欢迎纠错
Java学习之正则表达式篇相关推荐
- Java学习-17 正则表达式简述
Java学习-17 正则表达式 1.什么是正则表达式? 正则表达式是构成搜索模式(search pattern)的字符序列. 当您搜索文本中的数据时,您可使用搜索模式来描述您搜索的内容. 正则表达式可 ...
- 从.Net到Java学习第四篇——spring boot+redis
从.Net到Java学习系列目录 "学习java已经十天,有时也怀念当初.net的经典,让这语言将你我相连,怀念你......"接上一篇,本篇使用到的框架redis.FastJSO ...
- Java学习笔记——正则表达式(Pattern类、Matcher类和PatternSyntaxException)
目录 一.Pattern类 (一)Pattern 介绍 (二)Pattern 方法 二.Matcher类 (一)Matcher 类介绍 (二)Matcher 类方法 三.PatternSyntaxEx ...
- [Java学习之路篇] 设计原则与设计模式
编程可谓博大精深,按照不同的思路逻辑.框架规范编写出来的程序运行的效率都大相径庭.本篇并不只针对Java程序,应适用于所有编写的程序,是编程世界中的一套方法论,俗称编程套路.它们会出现在目前很多大公司 ...
- Java学习day028(正则表达式)
JavaSe的学习也已经接近尾声了,还有很多笔记没整理,先整理正则表达式的 后面整理的有些不是太认真,都以后在整理 正则表达式 1.什么是正则表达式 2.元字符 3.反义符 4.重复(位数/长度) 5 ...
- Java学习笔记-正则表达式的模式匹配
正则表达式(Regex)为被匹配的文本模式提供了简明扼要的规范. 关于正则表达式的语法,可以参考相关书籍和这个网址:http://edu.yesky.com/edupxpt/18/2143018.sh ...
- java学习,入门篇-HelloWorld
HelloWorld 学习资源:西部开源–秦疆,B站up主'遇见狂神说'. 新建一个用于存放代码的文件 在新建的文件中新建一个Java 文件 新建一个文件 更改后缀名为Hello.java 编码格式 ...
- java学习笔记-基础篇
Java基础篇 1-12 常识 13 this关键字 14参数传递 16 继承 17 访问权限 28-31异常 1-12 常识 1.文件夹以列表展示,显示扩展名,在地址栏显示全路径 2.javac编译 ...
- Java学习进阶知识篇
系列文章目录 提示:....................... 文章目录 系列文章目录 前言 一.类和对象 面向对象基本介绍 类的基本使用属性 构造方法和析构方法 对象 二. 总结 前言 提示:这 ...
最新文章
- 《预训练周刊》第27期:谷歌发布最新看图说话模型、GitHub:平台上30%的新代码受益于AI助手Copilot...
- Vivado和Quartus ii 中工程存档(Archive project)及打开
- C++ 中的模板类声明头文件和实现文件分离后,如何能实现正常编译?
- GDB入门:A GDB Tutorial with Examples
- 关于kafka的几个问题
- [译] 用 Redis 和 Python 构建一个共享单车的 app
- 获取ip地址 域名获取与解析
- yolov4训练自己的数据 灰度图像_还在为图像训练数据少发愁吗?那是因为你还不会这几招...
- flex布局(弹性布局)
- 这几种常见的工业机器人编程方法你都知道吗
- 高中数学40分怎么办_高二了数学40多分还有救吗?
- Fiddler报文分析-断点应用、模拟网络限速-HTTPS的 拦截
- 庄子“知”问题的深入探讨(转载)
- ERROR: You appear to be running an X server; please exit X before installing
- 广西电网|应急空天一体化通信系统方案
- android刷成windows7,牛人将Win7刷进了安卓手机 高手在民间!
- MySQL触发器+游标应用
- 山东大学软件学院人工智能导论(考试)——期末考试回忆版
- 绥化学院学报杂志绥化学院学杂志社绥化学院学报编辑部2022年第9期目录
- MATLAB - 辨识工具箱的使用