标签:表达 compile 建立 matcher类 sse 结合 一个 rgs 注意
目录
正则表达式是一个强大的字符串处理工具,可以对字符串进行查找、提取、分割、替换等操作。String类也提供了几个特殊的方法:
(1)boolean matches(String regex):判断该字符串是否匹配指定的正则表达式
(2)String replaceAll(String regex,String replacement):将该字符串匹配的regex的子串替换成replacement
(3)String replaceFirst(String regex,String replacement):将该字符串第一个匹配的regex的子串替换成replacement
(4)String[] split(String regex):以regex作为分割符,将字符串分割为多个字串
上面的这些特殊方法都依赖于Java提供的正在表达式支持,除此之外,Java还提供了Pattern和Matcher两个类专门用于提供正则表达式支持。
正则表达式就是一个用于匹配字符串的模板,可以匹配一批字符串,所以创建正则表达式就是创建一个特殊的字符串。
字符 | 解释 |
---|---|
x | 字符x(x代表任何合法字符) |
\0mnn | 八进制0mnn所表示的字符 |
\xhh | 十六进制0xhh所表示的字符 |
\uhhhh | 十六进制0xhhhh所表示的Unicode字符 |
\t | 制表符(‘\u0009‘) |
\n | 新行(换行)符‘\u000A‘ |
\r | 回车符(‘\u000D‘) |
\f | 换页符(‘\u000C‘) |
\a | 报警符(‘\u0007‘) |
\e | Escape符(‘\u001B‘) |
\cx | x对应的控制符。例如:\cM匹配Ctr-M.x必须是a-z或A-Z |
除此之外,正则表达式还有一些特殊字符,如果需要匹配这些特殊字符,就必须先将这些字符转义,也就是在前面加一个反斜线()
特殊字符 | 说明 |
---|---|
^ | 匹配输入字符串的开始位置。要匹配 "^" 字符本身,请使用 "\^" |
$ | 匹配输入字符串的结尾位置。要匹配$字符本身,请使用 "\$" |
() | 标记一个子表达式的开始和结束位置。要匹配小括号,请使用"反斜线+左圆括号"和"反斜线+右圆括号" |
[] | 用于确定中括号表达式的开始和结束位置。要匹配中括号,请使用"反斜线+左方括号"和"反斜线+右方括号" |
{} | 用于标记前面子表式出现的频度。要匹配大括号,请使用 "\{" 和 "\}" |
. | 匹配除了换行符(\n)以外的任意一个字符。要匹配小数点本身,请使用 "\." |
? | 指定前面子表达式可以出现零次或一次。要匹配 "?" 字符本身,请使用 "\?" |
+ | 指定前面子表达式可以出现一次或多次。要匹配 "+" 字符本身,请使用 "\+" |
* | 指定前面子表达式可以出现零次或多次。要匹配*字符本身,请使用 "\*" |
| | 指定两项之间任选一项。匹配 "|" 本身,请使用\| |
\ | 用于转义下一个字符或指定八进制、十六进制字符。如果需要匹配\字符请用‘\\‘ |
上面多个字符拼接起来,可以创建一个正则表达式,例如:
"\u0041\\\\"——匹配A"\u0061\t"——匹配a<制表符>
"\\?\\["——匹配?[
”通配符“是可以匹配多个字符的特殊字符。正则表达式中”通配符“远远超出了普通通配符的功能,它被称为预定义字符。
预定义字符 | 说明 |
---|---|
. | 可以匹配任何字符 |
\d | 匹配0-9的所有数字 |
\D | 匹配非数字 |
\s | 匹配所有的空白字符,包括空格、制表符、回车符、换行符 |
\S | 匹配所有非空白字符 |
\w | 匹配所有单词字符,包括0-9,26个英文字符和下划线 |
\W | 匹配所有非单词字符 |
记忆:.是省略的意思,可以匹配任何字符;d——digital数字;s——space空白;w——word单词(数字,字母、下划线)。大写代表匹配恰好相反的字符。
举例:
c\\wt//可以匹配cat\cbt\cct\c0t\c_t等一批字符
\\d\\d\\d-\\d\\d\\d-\\d\\d\\d\\d 匹配000-000-0000形式的电话号码
在一些特殊情况,例如只想匹配a~f的字母,或匹配除ab之外的所有小写字母,或者匹配中文字符,此时就需要方括号表达式。
方括号表达式 | 说明 |
---|---|
表示枚举 | 例如[abc],表示abc任何一个字符 |
表示范围- | 例如[a-f]表示a-f任何一个字符;[\u0041-\u0056]表示十六进制符\u0041-\u0056范围的字符。范围和枚举结合使用,[a-cx-z]表示a-c、x-z范围内的字符 |
表示求否^ | 例如[^abc],表示非abc的任意字符;[^a-f]表示非a~f范围内的任意字符 |
表示"与"运算:&& | [a-z&&[def]],求a-z与[def]之间的交集,表示d、e、f |
表示"并"运算 | 并运算与前面的枚举类似,例如[a-d[m-p]]表示[a-dm-p] |
圆括号表达式用于将多个表达式组成一个子表达式,圆括号中可以使用或运算符(|)。例如((public)|(private)|(protected))
边界匹配 | 含义 |
---|---|
^ | 一行的开始 |
$ | 一行的结束 |
\b | 单词的边界 |
\B | 非单词的边界 |
\A | 输入的开头 |
\G | 前一个匹配的结尾 |
\Z | 输入的结尾,仅用于最后的结束符 |
\z | 输入的结尾 |
前面匹配一个000-000-0000的电话号码时,使用了//d//d//d-//d//d//d-//d//d//d//d的正则表达式,这种看起来比较繁琐。实际上正则表达式提供的数量标识符可以很好地解决这种问题。数量表达式有三种模式:
(1)Greedy(贪婪)模式:表示符默认采用贪婪模式,除非另有表示。贪婪模式会一直匹配下去,直至无法匹配为止。
(2)Reluctant(勉强)模式:用后缀?表示,它只会匹配最少的字符。也称为最小匹配模式
(3)Possessive(占用)模式:用加号(+)后缀表示,目前Java支持占用模式,通常比较少用。
贪婪模式 | 勉强模式 | 占用模式 | 说明 |
---|---|---|---|
X? | X?? | X?+ | X表达式出现零次或一次 |
X* | X*? | X*+ | X表达式出现零次或多次 |
X+ | X+? | X++ | X表达式出现一次或多次 |
X{n} | X{n}? | X{n}+ | X表达式出现n次 |
X{n,} | X{n,}? | X{n,}+ | X表达式最少出现n次 |
X{n,m} | X{n,m}? | X{n,m}+ | X表达式最少出现n次,最多出现m次 |
关于贪婪模式与勉强模式的对比:
String str="hello ,java!";
System.out.println(str.replaceFirst("\w*","D"));//输出D ,java!
System.out.println(str.replaceFirst("\w*?","D"));//输出Dhello ,java
一旦程序中定义了正则表达式,就可以直接利用Pattern和Matcher来使用正则表达式
Pattern对象是正则表达式编译后在内存中的表示形式,因此正则表达式字符串必须鲜卑编译为Pattern对象,然后再利用Pattern对象创建对应的Matcher对象。执行匹配所涉及的状态保留在Matcher对象中,多个Matcher对象可共享一个Pattern对象。
典型的调用顺序:
//将一个字符串编译成Pattern对象
Pattern p=Pattern.compile("a*b");
//使用Pattern对象创建Matcher对象
Matcher m=p.matcher("aaaab");
boolean b=m.matches();//返回true
上面定义的Pattern对象可以多次重复使用,如果某个正则表达式仅需使用一次,可以直接使用Pattern类的静态matches()方法,此方法自动把指定字符串编译成匿名的Pattern对象,并执行匹配:
boolean b=Pattern.matches("a*b","aaaaab");//输出true
上面语句等效为前面的三条语句。但这种语句每次都需要重新编译新的Pattern对象,不能重复利用已编译的Pattern对象,所以效率不高。
Pattern是不可变类,可供多个并发线程安全使用。
Matcher类提供以下几个常用方法:
(1)find():返回字符串中是否包含与Pattern匹配的子串。
(2)group():返回上一次与Pattern匹配的子串。
(3)start():返回上一次与Pattern匹配的子串在目标字符串中开始的位置。
(4)end():返回上一次与Pattern匹配的子串在目标字符串中的结束位置+1.
(5)lookingAt():返回目标字符串前面部分与Pattern是否匹配。
(6)matches():返回整个目标字符串与Pattern是否匹配。
(7)reset():将现有的Matcher对象应用于一个新的字符串序列。
注意:在Pattern、Matcher类中常常会看到一个CharSequence接口,该接口代表一个字符序列,其CharBuffer、String、StringBuffer、StringBuilder都是它的实现类。简单来说,CharSequence代表一个各种表示形式的字符串。
通过Matcher类的find()、group()方法可以从目标字符串中依次取出指定的子串(匹配正则表达式的子串),例如互联网的网络爬虫,它们可以自动从网页中识别出所以电话号码。下面程序中示范了如何从大段字符串中找出电话号码:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class FindGroup
{
public static void main(String[] args)
{
//使用字符串模拟从网络上得到网页的源码
var str = "我想求购一本《疯狂Java讲义》,尽快联系我13500006666"
+ "交朋友,电话号码是13611125565"
+ "出售二手电脑,联系方式15899903312";
// 创建一个Pattern对象,并用它建立一个Matcher对象
// 该正则表达式只抓取13X和15X段的手机号,
// 实际要抓取哪些电话号码,只要修改正则表达式即可。
Pattern p=Pattern.compile("((13\\d)|(15\\d))\\d{8}");
Matcher m=p.matcher(str);
//将所有符合正则表达式的子串全部输出
while(m.find())
{
System.out.println(m.group());
}
}
}
---------- 运行Java捕获输出窗 ----------
13500006666
13611125565
15899903312
输出完成 (耗时 0 秒) - 正常终止
从上面的运行结果来看,find()方法依次查找字符串中与Pattern匹配的子串,一旦找到了对应的子串,下次调用find()方法将接着往下找。
find()方法还可以传入一个int类型的参数,带int类型参数的find()方法将从该int索引处向下搜索。
用于确定子串在目标字符中的位置,如下程序所示:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class StartEnd
{
public static void main(String[] args)
{
//创建一个Pattern对象,并用它建立它的Matcher对象
var regStr="Java is very easy!";
System.out.println("目标字符串是:"+regStr);
Matcher m=Pattern.compile("\\w+").matcher(regStr);
while(m.find())
{
System.out.println(m.group()+"子串起始位置:"+m.start()+",其结束位置:"+m.end());
}
}
}
---------- 运行Java捕获输出窗 ----------
目标字符串是:Java is very easy!
Java子串起始位置:0,其结束位置:4
is子串起始位置:5,其结束位置:7
very子串起始位置:8,其结束位置:12
easy子串起始位置:13,其结束位置:17
输出完成 (耗时 0 秒) - 正常终止
上面程序使用find()和group()方法逐项取出目标字符串与指定正则表达式匹配的子串,并使用start()、end()方法返回子串在目标字符串中的位置。
1、lookingAt():返回目标字符串前面部分与Pattern是否匹配。
2、matches():返回整个目标字符串与Pattern是否匹配。
区别在于matches()方法要求整个字符串和Pattern对象完全匹配时才返回true,而lookingAt()只要字符串以Pattern开头就返回true
3、reset():将现有的Matcher对象应用于一个新的字符串序列。
import java.util.regex.*;
public class MatchesTest
{
public static void main(String[] args)
{
String[] mails =
{
"kongyeeku@163.com",
"kongyeeku@gmail.com",
"ligang@crazyit.org",
"wawa@abc.xx"
};
var mailRegEx = "\\w{3,20}@\\w+\\.(com|org|cn|net|gov)";
var p=Pattern.compile(mailRegEx);
Matcher matcher=null;
for(var mail:mails)
{
if(matcher==null)
{
matcher=p.matcher(mail);
}
else
{
matcher.reset(mail);
}
String result=mail+(matcher.matches()?"是":"不是")+
"一个有效的邮件地址!";
System.out.println(result);
}
}
}
---------- 运行Java捕获输出窗 ----------
kongyeeku@163.com是一个有效的邮件地址!
kongyeeku@gmail.com是一个有效的邮件地址!
ligang@crazyit.org是一个有效的邮件地址!
wawa@abc.xx不是一个有效的邮件地址!
输出完成 (耗时 0 秒) - 正常终止
从上面创建了一个邮箱地址的Pattern,接着用这个Pattern与多个邮件地址进行匹配。当程序的Mathcer为null时,程序调用Parttern对象的matcher()方法来创建一个Matcher对象,一旦Matcher对象被创建,程序就调用Matcher对象的reset()方法将该Matcher应用于新的字符序列。
从某个角度来说,Matcher类的matches()、lookingAt()和String类的equals()、startsWith()有点类似,区别在于String类的equals()、startsWith()都是与字符串进行比较,而Matcher类的matches()、lookingAt()都是于正则表达式进行匹配。
事实上,String类也提供了matches()方法,该方法返回该字符串是否匹配指定的正则表达式。例如:
"kongyeeku@163.com".matches(\\w{3,20}@\\w+\\.(com|org|cn|net|gov));//返回true
import java.util.regex.*;
public class ReplaceTest
{
public static void main(String[] args)
{
String[] msgs =
{
"Java has regular expressions in 1.4",
"regular expressions now expressing in Java",
"Java represses oracular expressions"
};
var p=Pattern.compile("re\\w*");
Matcher matcher=null;
for(var i=0;i<msgs.length;i++)
{
if(matcher==null)
matcher=p.matcher(msgs[i]);
else
matcher.reset(msgs[i]);
System.out.println(matcher.replaceAll("哈哈:)"));
}
}
}
---------- 运行Java捕获输出窗 ----------
Java has 哈哈:) exp哈哈:) in 1.4
哈哈:) exp哈哈:) now exp哈哈:) in Java
Java 哈哈:) oracular exp哈哈:)
输出完成 (耗时 0 秒) - 正常终止
String类也提供了replaceAll()、replaceFirst()、split()方法。下面程序示范直接使用String类提供的正则表达式的功能来进行替换和分割。
import java.util.*;
public class StringReg
{
public static void main(String[] args)
{
String[] msgs =
{
"Java has regular expressions in 1.4",
"regular expressions now expressing in Java",
"Java represses oracular expressions"
};
for (var msg : msgs)
{
System.out.println(msg.replaceFirst("re\\w*", "哈哈:)"));
System.out.println(Arrays.toString(msg.split(" ")));
}
}
}
---------- 运行Java捕获输出窗 ----------
Java has 哈哈:) expressions in 1.4
[Java, has, regular, expressions, in, 1.4]
哈哈:) expressions now expressing in Java
[regular, expressions, now, expressing, in, Java]
Java 哈哈:) oracular expressions
[Java, represses, oracular, expressions]
输出完成 (耗时 0 秒) - 正常终止
标签:表达 compile 建立 matcher类 sse 结合 一个 rgs 注意
原文地址:https://www.cnblogs.com/weststar/p/12483376.html