恭喜你,Get到一份 正则表达式 食用指南
- 2020 年 3 月 30 日
- 笔记
先赞后看,养成习惯

前言
正则表达式
正则表达式: 定义一个搜索模式的字符串。
正则表达式可以用于搜索、编辑和操作文本。
正则对文本的分析或修改过程为:首先正则表达式应用的是文本字符串(text/string),它会以定义的模式从左到右匹配文本,每个源字符只匹配一次。
Java中正则表达式的使用
字符串内置正则
在 Java 中有四个内置的运行正则表达式的方法,分别是 matches()
、split())
、replaceFirst()
、replaceAll()
。注意 replace()
方法不支持正则表达式。
当仅且当正则匹配整个字符串时返回 true
示例代码
System.out.println("lby".matches("lby")); System.out.println("----------"); String[] array = "l b y".split("\s"); for (String item : array) { System.out.println(item); } System.out.println("----------"); System.out.println("l b y".replaceFirst("\s", "-")); System.out.println("----------"); System.out.println("l b y".replaceAll("\s", "-"));
运行结果
true ---------- l b y ---------- l-b y ---------- l-b-y
regex包
java.util.regex 包主要包括以下三个类:
- Pattern 类 pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
- Matcher 类 Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
- PatternSyntaxException PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。
Java 中regex 包使用正则表达式基本步骤
通过正则表达式创建模式对象 Pattern。
通过模式对象 Pattern,根据指定字符串创建匹配对象 Matcher。
通过匹配对象 Matcher,根据正则表达式操作字符串。
例如
import java.util.regex.Matcher; import java.util.regex.Pattern; public class TestRegex { public static void main(String[] args) { //定义一个字符串 String text = "Hello Regex!"; //创建一个Pattern对象 可以认为根据正则表达式获取一个对应的对象 Pattern pattern = Pattern.compile("\w+"); // Java 中忽略大小写,有两种写法: // Pattern pattern = Pattern.compile("\w+", Pattern.CASE_INSENSITIVE); // Pattern pattern = Pattern.compile("(?i)\w+"); // 推荐写法 Matcher matcher = pattern.matcher(text); // 遍例所有匹配的序列 while (matcher.find()) { System.out.print("Start index: " + matcher.start()); System.out.print(" End index: " + matcher.end() + " "); System.out.println(matcher.group()); } } }
运行的结果为:
Start index: 0 End index: 5 Hello
Start index: 6 End index: 11 Regex、
以上代码看不懂没有关系,提前感受一下正则的神奇,接下来我们学习一下正则表达式的的语法。
正则表达式的语法
常见匹配符号
匹配所有单个字符,除了换行符(Linux 中换行是 n,Windows 中换行是 rn)
元字符
元字符是一个预定义的字符。
匹配一个数字,是 [0-9] 的简写
限定符
限定符定义了一个元素可以发生的频率。
正则表达式 |
描述 |
举例 |
---|---|---|
* |
匹配 >=0 个,是 {0,} 的简写 |
X* 表示匹配零个或多个字母 X,.*表示匹配任何字符串 |
+ |
匹配 >=1 个,是 {1,} 的简写 |
X+ 表示匹配一个或多个字母 X |
? |
匹配 1 个或 0 个,是 {0,1} 的简写 |
X? 表示匹配 0 个或 1 个字母 X |
{X} |
只匹配 X 个字符 |
d{3} 表示匹配 3 个数字,.{10}表示匹配任何长度是 10 的字符串 |
{X,Y} |
匹配 >=X 且 <=Y 个 |
d{1,4} 表示匹配至少 1 个最多 4 个数字 |
*? |
如果 ? 是限定符 * 或 + 或 ? 或 {} 后面的第一个字符,那么表示非贪婪模式(尽可能少的匹配字符),而不是默认的贪婪模式 |
|
分组和反向引用
小括号 ()
可以达到对正则表达式进行分组的效果。
模式分组后会在正则表达式中创建反向引用。反向引用会保存匹配模式分组的字符串片断,这使得我们可以获取并使用这个字符串片断。
在以正则表达式替换字符串的语法中,是通过 $
来引用分组的反向引用,$0
是匹配完整模式的字符串(注意在 JavaScript 中是用 $&
表示);$1
是第一个分组的反向引用;$2
是第二个分组的反向引用,以此类推。
示例:
package com.baizhi.test; public class RegexTest { public static void main(String[] args) { // 去除单词与 , 和 . 之间的空格 String Str = "Hello , World ."; String pattern = "(\w)(\s+)([.,])"; // $0 匹配 `(w)(s+)([.,])` 结果为 `o空格,` 和 `d空格.` // $1 匹配 `(w)` 结果为 `o` 和 `d` // $2 匹配 `(s+)` 结果为 `空格` 和 `空格` // $3 匹配 `([.,])` 结果为 `,` 和 `.` System.out.println(Str.replaceAll(pattern, "$1$3")); // Hello, World. } }
上面的例子中,我们使用了 [.]
来匹配普通字符 .
而不需要使用 [\.]
。因为正则对于 []
中的 .
,会自动处理为 [.]
,即普通字符 .
进行匹配。
否定先行断言(Negative lookahead)
我们可以创建否定先行断言模式的匹配,即某个字符串后面不包含另一个字符串的匹配模式。
否定先行断言模式通过 (?!pattern)
定义。比如,我们匹配后面不是跟着 "b" 的 "a":
a(?!b)
指定正则表达式的模式
可以在正则的开头指定模式修饰符。
(?i)
使正则忽略大小写。(?s)
表示单行模式("single line mode")使正则的.
匹配所有字符,包括换行符。(?m)
表示多行模式("multi-line mode"),使正则的^
和$
匹配字符串中每行的开始和结束。
Java 中的反斜杠
反斜杠 在 Java 中表示转义字符,这意味着
在 Java 拥有预定义的含义。
这里例举两个特别重要的用法:
- 在匹配
.
或{
或[
或(
或?
或$
或^
或*
这些特殊字符时,需要在前面加上\
,比如匹配.
时,Java 中要写为\.
,但对于正则表达式来说就是.
。 - 在匹配
时,Java 中要写为
\\
,但对于正则表达式来说就是\
。
注意:Java 中的正则表达式字符串有两层含义,首先 Java 字符串转义出符合正则表达式语法的字符串,然后再由转义后的正则表达式进行模式匹配。
正则表达式常见应用示例
中文的匹配
[u4e00-u9fa5]+
代表匹配中文字。
public static void test3(){ String str = "这里有个新手易范的错误,就是正angongsi"; Pattern pattern = Pattern.compile("[\u4e00-\u9fa5]+"); Matcher matcher = pattern.matcher(str); while (matcher.find()) { System.out.println(matcher.group()); } }
数字范围的匹配
比如,匹配 1990 到 2017。
**注意:**这里有个新手易范的错误,就是正则 [1990-2017]
,实际这个正则只匹配 0
或 1
或 2
或 7
或 9
中的任一个字符。
正则表达式匹配数字范围时,首先要确定最大值与最小值,最后写中间值。
正确的匹配方式:
public static void test4(){ String str = "1990n2010n2017nsdfgadfggadfgdfgdfgafdgasfdgan1998"; // 这里应用了 (?m) 的多行匹配模式,只为方便我们测试输出 // "^1990$|^199[1-9]$|^20[0-1][0-6]$|^2017$" 为判断 1990-2017 正确的正则表达式 Pattern pattern = Pattern.compile("(?m)^1990$|^199[1-9]$|^20[0-1][0-6]$|^2017$"); Matcher matcher = pattern.matcher(str); while (matcher.find()) { System.out.println(matcher.group()); } }
img 标签的匹配
比如,获取图片文件内容,这里我们考虑了一些不规范的 img 标签写法:
public static void test5(){ String str = "<img src='aaa.jpg' /><img src=bbb.png/><img src="ccc.png"/>" + "<img src='ddd.exe'/><img src='eee.jpn'/>"; // 这里我们考虑了一些不规范的 img 标签写法,比如:空格、引号 Pattern pattern = Pattern.compile("<img\s+src=(?:['"])?(?<src>\w+.(jpg|png))(?:['"])?\s*/>"); Matcher matcher = pattern.matcher(str); while (matcher.find()) { System.out.println(matcher.group("src")); } }
邮箱匹配
邮箱匹配的正则的写法有很多,这里给出一种参考的写法。
合法E-mail地址:
- 必须包含一个并且只有一个符号“@”
- 第一个字符不得是“@”或者“.”
- 不允许出现“@.”或者.@
- 结尾不得是字符“@”或者“.”
- 允许“@”前的字符中出现“+”
- 不允许“+”在最前面,或者“+@”
等等
示例代码
public static void test6(){ String check = "^([a-z0-9A-Z]+[-|\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\.)+[a-zA-Z]{2,}$"; Pattern regex = Pattern.compile(check); Matcher matcher = regex.matcher("[email protected]"); boolean isMatched = matcher.matches(); System.out.println(isMatched); }
手机号匹配
public static void test7(){ String check = "^((13[0-9])|(15[^4])|(18[0-9])|(17[0-9])|(147))\d{8}$"; Pattern regex = Pattern.compile(check); Matcher matcher = regex.matcher("18638693953"); boolean isMatched = matcher.matches(); System.out.println(isMatched); }
url匹配
public static void test8(){ String url = "http://www.lubingyang.com/"; String regex = "(https?://(w{3}\.)?)?\w+\.\w+(\.[a-zA-Z]+)*(:\d{1,5})?(/\w*)*(\??(.+=.*)?(&.+=.*)?)?"; boolean isMatched = Pattern.matches(regex, url); System.out.println(isMatched); }