文章目录
前言
1.一个正则表达式,就是用某种模式去匹配字符串的一个公式。很多人因为它们看上去比较古怪而且复杂所以不敢去使用,不过,经过练习后,就觉得这些复杂的表达式写起来还是相当简单的,而且,一旦你弄懂它们,你就能把数小时辛苦而且易错的文本处理工作缩短在几分钟(甚至几秒钟)内完成
2.这里要特别强调,正则表达式不是只有java才有,实际上很多编程语言都支持正则表达式进行字符串操作!如图所示。
一、 正则表达式语法
1.0基本介绍
如果要想灵活的运用正则表达式,必须了解其中各种元字符的功能,元字符从功能上大致分为:
1.限定符
2.选择匹配符
3.分组组合和反向引用符
4. 特殊字符
5.字符匹配符
6.定位符
1.1 元字符(Metacharacter)
1.11 转义号 \\
🏃注意:需要用到转义符号有一下:. * () $ / \ [ ] ^ { }\ \符号 说明:在我们使用正则表达式去检索某些特殊字符的时候,需要用到转义符号,否则检索不到结果,甚至会报错。
提示
:在JAVA的正则表达式中,两个\\代表其他语言中的一个\。
代码如下(示例):
package 正则表达式;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegExp02 {
public static void main(String[] args) {
String content="ab.c$(a.bc(123(";
//匹配(=>\\(
//匹配.=>\\.,否则.表示匹配所有的字符
//String reStr="\\(";
//String reStr="\\.";
//String reStr="\\d\\d\\d";
String reStr="\\d{3}";
Pattern pattern= Pattern.compile(reStr);
Matcher matcher=pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到"+matcher.group(0));
}
}
}
1.12 字符匹配符
符号 | 含义 | 示例 | 解释 |
---|---|---|---|
[] | 可接收的字符列表 | [efgd] | e、f、g、h中的任意1个字符 |
[^] | 不接收的字符列表 | [^abc] | 除a、b、c之外的任意1个字符,包括数字和特殊符号 |
- | 连字符 | A-Z | 任意单个大写字母 |
. | 匹配除\n以外的任何字符 | a…b | 以a开头,b结尾,中间包括2个任意字符的长度为4的字符串,eg:aaab,aefb、a35b、a#*b |
\\d | 匹配单个数字字符,相当于[0-9] | \\d{3}(\\d)? | 包含31个或4个数字的字符串eg:123、9876 |
\\D | p匹配单个非数字字符,相当于[^0-9] | \\D(\\d)* | 以单个非数字字符开头,后接任意个数字字符串eg:a、A342 |
\\w | 匹配单个数字、大小写字母字符相当于[0-9a-zA-Z] | \\d{3}\\w | 以3个数字字符开头的长度为7的数字字母字符串eg:234abcd、12345Pe |
\\W | 匹配单个非数字、大小写字母字符相当于[0-9a-zA-Z] | \\W+\\d{2} | 以至少1个非数字字母字符开头,2个数字字符结尾的字符串eg:#29、#?@10 |
光看这个是不太行的喔!上代码(建议各位小宝贝自己动手打一遍!!!)
package 正则表达式;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*演示字符匹配符的使用*/
public class RegExp03 {
public static void main(String[] args) {
String content="abc11c_8abc\nABCy @";
// String regStr="[a-z]";//匹配a-z之间的任意一个字符
// String regStr="[A-Z]";//匹配A-Z之间的任意一个字符
// String regStr="abc";//匹配 abc字符串(默认区分大小写)
// String regStr="(?i)abc";//匹配 abc字符串(不区分大小写)
// 说明:1.当创建Pattern对象时,指定 Pattern.CASE_INSENSITIVE,表示匹配是不区分字母大小写。
// Pattern pattern=Pattern.compile(regStr,Pattern.CASE_INSENSITIVE);
// String regStr="[0-9]";//匹配0-9之间的任意一个字符
// String regStr="[^a-z]";//匹配不在a-z之间任意一个字符
// String regStr="[^0-9]";//匹配不在0-9之间任意一个字符
// String regStr="[abcd]";//匹配在abcd中的任意字符
// String regStr="\\D";//匹配不在0-9之间任意一个字符
// String regStr="\\w";//匹配 大小写英字,下划线 文字母,数
// String regStr="\\s";//匹配任何空白字符(空格,制表符等)
// String regStr="\\S";//匹配非任何空白字符
String regStr=".";//匹配\n之外的所有字符,如果要匹配.本身则需要使用\\.
Pattern pattern=Pattern.compile(regStr);
Matcher matcher=pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到 "+matcher.group(0));
}
}
}
1.13选择匹配符
在匹配某个字符串的时候是选择性,即:既可以匹配这个,又可以匹配那个,这时你需要用到 选择匹配符 |
//例如:
public class RegExp04 {
public static void main(String[] args) {
String content="liudehua 牛 流水";
String regStr="liu|牛|流";
Pattern pattern = Pattern.compile(regStr/*, Pattern.CASE_INSENSITIVE*/);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到 " + matcher.group(0));
}
}
}
1.14 限定符
限定符:用于指定其前面的字符和组合项连续出现多少次。
符号 | 含义 | 示例 | 说明 | 匹配输入 |
---|---|---|---|---|
* | 指定字符重复0次或n次(无要求)零到多 | (abc)* | 仅包含任意个abc的字符串,等效于\w* | abc/abcabcabc |
+ | 指定字符重复1次或n次(至少1次) | m+(abc)* | 以至少1个m开头,后接任意个abc的字符串 | m、 mabc、mabcabc |
? | 指定字符重复0次或1次(最多一次)0到1 | m+abc? | 以至少1个m开头,后接ab或者abc的字符串 | mab,mabc,mmmab,mmabc |
{n} | 只输入n个字符 | [abcd]{3} | 由abcd中字母组成的任意长度为3的字符串 | abc,dbc,adc |
{n,} | 指定匹配至少n个匹配 | [abcd]{3,} | 由abcd中字母组成的任意长度不小于3的字符串 | aab,dbc,aaabdc |
{n,m} | 指定至少n个但不多于m个匹配 | [abcd]{3,5} | 由abcd中字母组成的任意长度不小于3不大于5的字符串 | abc,abcd,aaaaa,bcdab |
package 正则表达式;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegExp05 {
public static void main(String[] args) {
String content="a11111111aaaaaahello";
// String regStr="a{3}";// 表示匹配 aaa
// String regStr="1{3}";// 表示匹配 111
// String regStr="\\d{2}";// 表示匹配 两位的任意数字字符
// a{3,4},1{4,5},\\d{2,5}
//细节:java匹配默认贪婪匹配,即尽可能匹配多的
// String regStr="a{3,4}";// 表示匹配 aaaa
// String regStr="1{4,5}";// 表示匹配 1111或11111
// String regStr="\\d{2,5}";// 表示匹配 两位数或者3,4,5
//1+
// String regStr="1+";//表示匹配1个1或者多个1
//1*
// String regStr="1*";//表示匹配0个1或者多个1
//演示?的使用,遵循贪婪匹配
String regStr="a1?";//匹配a或者a1
Pattern pattern=Pattern.compile(regStr);
Matcher matcher=pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到 "+matcher.group(0));
}
}
}
1.15定位符
定位符:规定要匹配的字符出现的位置,比如在字符串的开始还是结束的位置。必须掌握
符号 | 含义 | 示例 | 说明 | 匹配输入 |
---|---|---|---|---|
^ | 指定起始字符 | ^ [0-9]+[a-z]* | 以至少1个数字开头,后接任意个小写字母的字符串 | 123、6aa、555edf |
\\b | 匹配目标字符串的边界 | han\\b | 这里说的字符串边界指的是子串间有空格,或者目标字符串的结束位置 | hanshunping sphan nnhan |
\\B | 匹配目标字符串的非边界 | han\\B | 和\\b的含义刚刚相反 | hangshunping sphan nnhan |
package 正则表达式;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*演示定位符*/
public class RegExp06 {
public static void main(String[] args) {
// String content="123abc";
String content="hanshunping aphan nnhan";
//以至少1个数字开头,后接任意个小写字母的字符串
// String regStr="^[0-9]+[a-z]*";
//以至少1个数字开头,必须以至少一个小写字母结束($)
// String regStr="^[0-9]+\\-[a-z]+$";
//表示匹配边界的han[这里的边界是指:被匹配字符串最后,
//也可以是空格的子字符串的后面
// String regStr="han\\b";
// 和\\b的含义相反
String regStr="han\\B";//第一个han
Pattern pattern=Pattern.compile(regStr);
Matcher matcher= pattern.matcher(content);
while(matcher.find()){
System.out.println("找到="+matcher.group(0));
}
}
}
1.16 分组
常用分组构造形式 | 说明 |
---|---|
(pattern) | 非命名捕获。捕获匹配的子字符串。编号为0的第一个捕获是由整个正则表达式模式匹配的文本,其它捕获结果则根据左括号的顺序从1开始自动编号 |
(?pattern) | 命名捕获,将匹配的字符串捕获到一个组名称或编号名称中,用于name的字符串,不能包含任何标点字符,并且不能以数字开头,可以使用单引号替代尖括号,例如(?‘name’) |
(?:pattern) | 匹配pattern但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配,这对于用“or"字符(|)组合模式部件的情况很有用。例如:‘industr(?y|ies)是比’industry|industries’更经济的表达式 |
(?=pattern) | 它是一个非捕获匹配。例如:‘Windows(?=95|NT|2000)'匹配”Windows 2000"中的“WIndows",但不匹配”Windows 3.1"中的“WIndows" |
(?pattern) | 该表达式匹配不处于匹配patten的字符串的起始点的搜索字符串。它是一个非捕获匹配。例如,‘Windows(?!95|NT|2000)'匹配”Windows 3.1"中的“WIndows",但不匹配”Windows 2000"中的“WIndows" |
package 正则表达式;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*分组*/
public class RegExp07 {
public static void main(String[] args) {
String content="hanshunping s7789 nn1189han";
//下面就是非命名分组
/* 说明*/
//1.matcher.group(0) 得到匹配到的字符串
//2.matcher.group(1) 得到匹配到的字符串的第1个分组内容
//3.matcher.group(2) 得到匹配到的字符串的第2个分组内容
// String reStr="(\\d\\d)(\\d\\d)";
//命名分组:即可以给分组取名?<name>
String reStr="(?<g1>\\d\\d)(?<g2>\\d\\d)";
Pattern pattern=Pattern.compile(reStr);
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个分组内容[通过组名]="+matcher.group(("g1")));
System.out.println("第2个分组内容="+matcher.group(2));
System.out.println("第2个分组内容[通过组名]="+matcher.group(("g2")));
}
}
}
package 正则表达式;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**演示非捕获分组,语法比较奇怪*/
public class RegExp08 {
public static void main(String[] args) {
String content="hello新东方教育 john新东方老师 新东方同学hello";
//找到 新东方教育、新东方老师、新东方同学 子字符串
// String regStr="新东方教育|新东方老师|新东方同学";
//等价于非捕获分组,注意:不能 matcher.group(1)
//String regStr="新东方(?:教育|老师|同学)";
//找到 新东方 这个关键字,但是要求只是查找新东方教育 和 新东方老师 中包含的新东方
// String regStr="新东方(?=教育|老师)";
//找到 新东方 这个关键字,但是要求只是查找 不是 新东方教育 和 新东方老师 中包含的新东方
String regStr="新东方(?!教育|老师)";
Pattern pattern=Pattern.compile(regStr);
Matcher matcher= pattern.matcher(content);
while(matcher.find()){
System.out.println("找到:"+matcher.group(0));
//System.out.println("找到:"+matcher.group(1));
}
}
}
package 正则表达式;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**非贪婪匹配*/
public class RegExp09 {
public static void main(String[] args) {
String content="hello11111 ok";
//String regStr="\\d+";//默认是贪婪匹配
String regStr="\\d+?";//非贪婪匹配 ?表示1到多
Pattern pattern=Pattern.compile(regStr);
Matcher matcher= pattern.matcher(content);
while(matcher.find()){
System.out.println("找到:"+matcher.group(0));
//System.out.println("找到:"+matcher.group(1));
}
}
}
package 正则表达式;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ReExp10 {
public static void main(String[] args) {
//汉字
String content="13588889999";
//String regStr="^[\u0391-\uffe5]+$";
//邮政编码 要求:是1-9开头的一个六位数,比如:123890
// String regStr="^[1-9]\\d{5}$";
//QQ号码
//要求:是1-9开头的一个(5-10位数)
//12389,1345687
//String regStr="^[1-9]\\d{4,9}$";
//手机号
//要求:必须13,14,15,18 开头的11位数,比如13588889999
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(matcher.group(0));
System.out.println("满足格式");
}else{
System.out.println("不满足格式");
}
//邮政编码
}
}
1.17 分组、捕获、 反向引用
1.分组
我们可以用圆括号组成一个比较复杂的匹配模式,那么一个圆括号的部分我们可以看作是一个子表达式/一个分组
2.捕获
把正则表达式中子表达式/分组匹配的内容,保存到内存中以数字编号或显示命名的组里,方便后面引用,从左到右,以分组的左括号为标志,第一个出现的分组的组好为1,第二个为2,以此类推,组0代表的是这个正则表达式。
3.反向引用
圆括号的内容被捕获后,可以在这个括号后使用,从而写出一个比较实用的匹配模式,这个我们称为反向引用,这种引用既可以是在正则表达式内部,也可以是在正则表达式外部,内部反向引用\分组号,外部反向引用$分组号。
package 正则表达式;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegExp13 {
public static void main(String[] args) {
String content="我...我要...学学学学...编程java!";
//1. 去掉所有的.
Pattern pattern = Pattern.compile("\\.");
Matcher matcher = pattern.matcher(content);
content = matcher.replaceAll("");
// System.out.println("content=" + content);
// 2. 去掉重复的字 我我要学学学学编程 java!
// 思路
// (1) 使用 (.)\\1+
// (2) 使用 反向引用$1 来替换匹配到的内容
// 注意:因为正则表达式变化,所以需要重置 matcher
// pattern = Pattern.compile("(.)\\1+");//分组的捕获内容记录到$1
// matcher = pattern.matcher(content);
// while (matcher.find()) {
//
// System.out.println("找到=" + matcher.group(0));
// }
//
// //使用 反向引用$1 来替换匹配到的内容
// content = matcher.replaceAll("$1");
// System.out.println("content=" + content);
//3. 使用一条语句 去掉重复的字 我我要学学学学编程 java!
content = Pattern.compile("(.)\\1+").matcher(content).replaceAll("$1");
System.out.println("content=" + content);
}
}
1.18 String 类中使用正则表达式
public class StringReg {
public static void main(String[] args) {
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 的计算能力有了大幅提升";
//使用正则表达式方式,将 JDK1.3 和 JDK1.4 替换成 JDK
content = content.replaceAll("JDK1\\.3|JDK1\\.4", "JDK");
System.out.println(content);
//要求 验证一个 手机号, 要求必须是以 138 139 开头的
content = "13888889999";
if (content.matches("1(38|39)\\d{8}")) {
System.out.println("验证成功");
} else {
System.out.println("验证失败");
}
//要求按照 # 或者 - 或者 ~ 或者 数字 来分割
System.out.println("===================");
content = "hello#abc-jack12smith~北京";
String[] split = content.split("#|-|~|\\d+");
for (String s : split) {
System.out.println(s);
}
}
}
总结
提示:这里对文章进行总结:
以上就是正则表达式的基本知识点和内容,希望大家可以好好消化一下,如果你觉得还有补充的,请在评论区留言,欢迎大家来指正。