一、什么是正则
我个人理解是,正则就是一套用来处理字符串的规则。比如字符串的匹配,替换等操作都能通过正则表达式来实现。其实在我们最开始学习java的时候,就或多或少的接触到这个所谓的正则表达式了。我们熟知的String类的replaceAll(String regex, String replacement) ,split(String regex)和startsWith(String prefix)等方法就是对正则的简单应用(regex就是正则表达式)。但是当初在不了解正则的时候,我用着也没问题啊。直到有一天遇到一些特殊字符(eg. + * [ ]),然后我就翻车了。。。
二、 正则常用语法
这里仅仅简单的介绍下正则的基本语法。以后遇到实际问题时,只需要通过这些基本语法的组合应用来满足我们的需求。
单个字符表示
表达式 | 含义 |
---|---|
. | 表示任意一个的字符 |
\d | 表示数字 |
\D | 表示非数字 |
\s | 表示由空字符组成,如空格,换行符(\n),制表符(\t)等 |
\S | 表示由非空字符组成 |
\w | 表示字母、数字、下划线 |
\W | 表示不是由字母、数字、下划线组成 |
\特殊字符 | 表示特殊字符,如 \[, \+, \*, \- 等 |
字符数量表示式
表达式 | 含义 |
---|---|
? | 表示出现0次或1次 |
+ | 表示出现1次或多次 |
* | 表示出现0次、1次或多次 |
{n} | 表示出现n次 |
{n,m} | 表示出现n~m次 |
{n,} | 表示出现n次或n次以上 |
字符取值范围表示
表达式 | 含义 |
---|---|
[abc] | 表示可能是a,可能是b,也可能是c |
[^abc] | 表示不是a,b,c中的任意一个 |
[a-zA-Z] | 表示是英文字母 |
[0-9] | 表示是数字 |
逻辑表达式
表达式 | 含义 |
---|---|
XY | 表示X后面跟着Y,这里X和Y分别是正则表达式的一部分 |
(X) | 子表达式,将X看做是一个整体 |
X|Y | 比如 “food|f”匹配的是food或foof,而 “(food)|f”匹配的是food或f |
三、java中正则使用
直接上代码:
package com.cydia.blog_test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test {
public static void main(String[] args){
String str = "a123cdf4*+";
System.out.println("source str = " + str);
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(str);
while(matcher.find()){
String ret = matcher.group();
System.out.println("match ret = " + ret);
}
}
}
输出如下:
source str = a123cdf4*+
match ret = 123
match ret = 4
注:在java中 “\”要改成 “\\”,如 “\d”要写成 “\\d”。否则会报错如下:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Invalid escape sequence (valid ones are \b \t \n \f \r \" \' \\ )
四、正则进阶
正则的匹配模式一共有三种:Greedy(贪婪),Reluctant(勉强),Possessive(独占)。
以字符串aaaa5bbbb6ccccc”为例,具体代码如下:
public class Test {
public static void main(String[] args){
String str = "aaaa5bbbb6ccccc";
System.out.println("source str = " + str);
//正则匹配
Pattern pattern = Pattern.compile(".{3,10}[0-9]");
Matcher matcher = pattern.matcher(str);
System.out.println("=====match start=====");
while(matcher.find()){
String ret = matcher.group();
System.out.println("match ret = " + ret);
}
System.out.println("=====match end=====");
}
}
输出对比如下:
对比 | Greedy | Reluctant | Possessive |
---|---|---|---|
正则表达式 | .{3,10}[0-9] | .{3,10}?[0-9] | .{3,10}+[0-9] |
匹配结果 | match ret = aaaa5bbbb6 | match ret = aaaa5 match ret = bbbb6 | 匹配不到 |
原理分析:
Greedy(贪婪匹配模式):正则表达式引擎会从头一直匹配到字符串最后,当匹配为false时,通过回溯的方式,倒退找到倒数第一个匹配位置,返回匹配结果。它也是java 正则表达式默认的匹配方式。
Reluctant(勉强匹配模式):正则表达式引擎会从头匹配到符合pattern的末尾位置那个字符,然后再往后走一步,发现匹配为false, 又回溯到找到回退的最近一个匹配为true的位置,返回匹配结果。
Possessive(独占匹配模式):总是读入整个输入串,尝试一次(仅且一次)匹配成功。