概念
正则表达式,又称正规表示式、正规表示法、正规表达式、规则表达式、常规表示法(英语:Regular Expression,在代码中常简写为regex、regexp或RE),是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些匹配某个模式的文本。
相关类
java.util.regex 包主要包括以下三个类:
-
Pattern 类: pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
-
Matcher 类: Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
-
PatternSyntaxException: PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。
案例解析
HelloWorld
String expression = "HelloWorld";
// 创建 Pattern 对象
Pattern pattern = Pattern.compile(expression);
// 现在创建 Matcher 对象
Matcher matcher = pattern.matcher("HelloWorld");
if (matcher.matches()) {
System.out.println("匹配");
} else {
System.out.println("不匹配");
}
我们以 HelloWorld 字符串作为正则表达式参数创建了一个 Pattern 对象,接着传入一个需要匹配的字符串(这里为 HelloWorld ),创建了 Matcher 对象,程序的最后打印结果为:
成功
代表正则匹配成功。
匹配 url
比如有url如下
http://www.abc.com/1.html
http://www.abc.com/2.html
如果使用如下正则表达式:
String expression = "http://www.abc.com/1.html";
就只能匹配 http://www.abc.com/1.html
,http://www.abc.com/2.html
匹配不了。
修改为如下:
String expression = "http://www.abc.com/\\d+\\.html"
两个都能匹配了。
String expression = "http://www.abc.com/\\d+\\.html"
// 创建 Pattern 对象
Pattern pattern = Pattern.compile(expression);
// 现在创建 Matcher 对象
Matcher matcher = pattern.matcher("http://www.abc.com/1.html");
if (matcher.matches()) {
System.out.println("匹配");
} else {
System.out.println("不匹配");
}
注意上面 expression 中的 \\d+
,这个代表正则表达式模式语法。这也是很多人觉得正则表达式是噩梦的原因,可能觉得该模式语法很奇怪。
比如 \\d+
是由两个语法组成的:
\d
:数字字符匹配。等效于 [0-9]。+
:一次或多次匹配前面的字符或子表达式。例如,"zo+"与"zo"和"zoo"匹配,但与"z"不匹配。+ 等效于 {1,}。
组合起来可以解释为,匹配一个或者多个数字,比如:1,2,222,4344,都能匹配成功。
所以使用 String expression = "http://www.abc.com/\\d+\\.html"
来匹配 http://www.abc.com/1.html
是可以成功的。
还有一个 \\.
也需要解释一下,因为点号 .
在正则表达式语法里面有特殊意义,需要转义一下,所以 \\.
代表匹配点号 .
。
String expression = "."
可以匹配除"\r\n"之外的任何单个字符,比如:a
,b
,c
。如果想匹配点号 .
,可以写 String expression = "\\."
,这样就只能匹配单个点号 .
了。
两个斜线的问题
在其他语言中,\\
表示:我想要在正则表达式中插入一个普通的(字面上的)反斜杠,请不要给它任何特殊的意义。
在 Java 中,\\
表示:我要插入一个正则表达式的反斜线,所以其后的字符具有特殊的意义。
所以,在其他的语言中,一个反斜杠 \
就足以具有转义的作用,而在正则表达式中则需要有两个反斜杠才能被解析为其他语言中的转义作用。也可以简单的理解在正则表达式中,两个 \
代表其他语言中的一个 \
,这也就是为什么表示一位数字的正则表达式是 \\d
,而表示一个普通的反斜杠是 \\\\
。
正则表达式语法
匹配和操作分组
在每种模式中,通过将模式的各部分放在圆括号中来创建分组。分组从左向右编号,从 1 开始编号(分组 0 表示完整的匹配结果,代表整个表达式)。
比如上面匹配 url 的正则表达式,String expression = "http://www.abc.com/\\d+\\.html"
来匹配 http://www.abc.com/1.html
和 http://www.abc.com/2.html
,想要获得那个匹配的数字 1 和 2,可以修改如下:
String expression = "http://www.abc.com/(\\d+)\\.html";
// 创建 Pattern 对象
Pattern pattern = Pattern.compile(expression);
// 现在创建 Matcher 对象
Matcher matcher = pattern.matcher("http://www.abc.com/1.html");
if (matcher.matches()) {
System.out.println("匹配");
System.out.println("group0:" + matcher.group());
System.out.println("group1:" + matcher.group(1));
} else {
System.out.println("不匹配");
}
结果如下:
匹配
group0:http://www.abc.com/1.html
group1:1
可以看到,我们获取到了那个匹配的数字。
我们在原来 \\d+
的基础上,加了一对括号 (\\d+)
,因为 String expression = "http://www.abc.com/(\\d+)\\.html"
里面只有一对括号,所以 (\\d+)
这部分代表第一组。
再来一个稍微复杂点儿的,比如想获得 3室1厅2卫
中的 3,1,2,可以如下做
String expression = "(\\d)\\D(\\d)\\D(\\d)\\D";
// 创建 Pattern 对象
Pattern pattern = Pattern.compile(expression);
// 现在创建 Matcher 对象
Matcher matcher = pattern.matcher("3室1厅2卫");
if (matcher.matches()) {
System.out.println("匹配");
System.out.println("group0:" + matcher.group());
System.out.println("group1:" + matcher.group(1));
System.out.println("group2:" + matcher.group(2));
System.out.println("group3:" + matcher.group(3));
} else {
System.out.println("不匹配");
}
结果如下:
匹配
group0:3室1厅2卫
group1:3
group2:1
group3:2
String expression = "(\\d)\\D(\\d)\\D(\\d)\\D"
解释如下,从左往右读:
- 第1个字符匹配一个数字,而且为第1组
- 第2个字符匹配一个非数字
- 第3个字符匹配一个数字,而且为第2组
- 第4个字符匹配一个非数字
- 第5个字符匹配一个数字,而且为第3组
- 第6个字符匹配一个非数字