java-正则表达式

时间:2022-12-01 19:56:40


1.一般流程

Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher("aaaaab");
boolean b = m.matches();

boolean b = Pattern.matches("a*b", "aaaaab");
boolean b = "aaaaab".matches("a*b");

第一种,当需要匹配多个字符串时,效率高。

2.几个重要的元字符(metacharacter)

.代表一个字符
*代表0或多个
+代表1或多个
?代表0或1个
\d 一个数字
\s A whitespace character: [ \t\n\x0B\f\r]
\w A word character: [a-zA-Z_0-9]

注意:java中匹配一个\主要四个“\\”

System.out.println("\\".matches("\\\\"));

输出true

3.范围

[abc] 表示匹配a或b或c中的一个
[^abc] 表示任意一个字符除了a或b或c
无论[]内多复杂,它只匹配一个字符

4.边界匹配

^ The beginning of a line
$ The end of a line
\b A word boundary

注意^位于[]内部是取反,否则是便是一行的开始。

System.out.println("hello sir".matches("^h[a-z]{1,4}\\b.*"));

输出true

5.Matcher类的几个函数

find():每次匹配还没剩下的子串
lookingAt():每次从头开始匹配
start():匹配的开始位置,end()匹配的结束的下一个位置。左闭右开空间

Pattern p = Pattern.compile("\\d{3,5}");
Matcher m = p.matcher("123-5435656-234-00");

while(m.find()){
System.out.println(m.start()+":"+m.end());
}

0:3
4:9
12:15

6.字符串匹配替换

public static void main(String[] args) {
Pattern p = Pattern.compile("java",Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher("java Java JAVA ilovejava end");

//全部转换成JAVA
// System.out.println(m.replaceAll("JAVA"));
//JAVA JAVA JAVA iloveJAVA end

StringBuffer sb=new StringBuffer();
int i=0;
while(m.find()){
if(i%2==0){
m.appendReplacement(sb, "java");
}else{
m.appendReplacement(sb, "JAVA");
}
i++;
}
//不加这句,后面的end就没有
m.appendTail(sb);

System.out.println(sb);
//java JAVA java iloveJAVA end
}

7.分组

注意整个字符是第0组。

public static void main(String[] args) {
Pattern p = Pattern.compile("(\\d{3,5})([a-z]{2})");
Matcher m = p.matcher("123aa-13242bb-456cc-00");

//只输出匹配到的字母部分
while(m.find()){
System.out.println(m.group(2));
}

}

输出
aa
bb
cc

8.quantifiers

有三种quantifiers,分别是Greedy,Reluctant(勉强),Possessive (侵占)
在贪婪、勉强和侵占三个量词间有着细微的不同。
  贪婪(*, ?, +):读入整个串,从后往前匹配
  勉强(*?, ??, +?):从前往后匹配
  侵占(*+, ?+, ++):读入整个串,从前往后匹配,匹配的是整个串
  贪婪量词之所以称之为“贪婪的”,这是由于它们强迫匹配器读入(或者称之为吃掉)整个输入的字符串,来优先尝试第一次匹配,如果第一次尝试匹配(对于整个输入的字符串)失败,匹配器会通过回退整个字符串的一个字符再一次进行尝试,不断地进行处理直到找到一个匹配,或者左边没有更多的字符来用于回退了。赖于在表达式中使用的量词,最终它将尝试地靠着 1 或 0 个字符的匹配。
  但是,勉强量词采用相反的途径:从输入字符串的开始处开始,因此每次勉强地吞噬一个字符来寻找匹配,最终它们会尝试整个输入的字符串。
  最后,侵占量词始终是吞掉整个输入的字符串,尝试着一次(仅有一次)匹配。不像贪婪量词那样,侵占量词绝不会回退,即使这样做是允许全部的匹配成功。

public static void main(String[] args) {
//Greedy
Pattern p = Pattern.compile(".{3,10}[0-9]");
Matcher m = p.matcher("aaaa4bbbb6");
if(m.find()){
System.out.println(m.start()+":"+m.end());
}else{
System.out.println("not match");
}
}

输出0:10

public static void main(String[] args) {
//Reluctant
Pattern p = Pattern.compile(".{3,10}?[0-9]");
Matcher m = p.matcher("aaaa4bbbb6");
if(m.find()){
System.out.println(m.start()+":"+m.end());
}else{
System.out.println("not match");
}
}

输出0:5

public static void main(String[] args) {
//Possessive
Pattern p = Pattern.compile(".{3,10}+[0-9]");
Matcher m = p.matcher("aaaa4bbbb6");
if(m.find()){
System.out.println(m.start()+":"+m.end());
}else{
System.out.println("not match");
}
}

输出not match
Possessive 型匹配失败是因为整个字符串已经被”.{3,10}+”匹配完成了,后面的”[0-9]”没有东西匹配,所以匹配失败。