什么是正则表达式?
正则表达式(Regular Expression,简称 Regex) 是用于匹配、搜索、替换字符串的强大工具。它通过特定的模式(Pattern),匹配文本中的特定字符组合,广泛应用于数据验证、文本处理、爬虫、日志分析等场景。
基本语法
字符 |
描述 |
^ |
匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 ‘\n’ 或 ‘\r’ 之后的位置。 |
$ |
匹配输入字符串的结束位置。如果设置了 RegExp 对象的 Multiline 属性,$ 也匹配 ‘\n’ 或 ‘\r’ 之前的位置。 |
* |
匹配前面的子表达式零次或多次。例如:‘zo*’ 能匹配 “z” 以及 “zoo”。* 等价于{0,}。 |
+ |
匹配前面的子表达式一次或多次。例如:‘zo+’ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等价于 {1,}。 |
? |
匹配前面的子表达式零次或一次。例如:‘do(es)?’ 可以匹配 “do” 或 “does” 中的 “do” 。? 等价于 {0,1}。 |
() |
标记一个子表达式的开始和结束位置。 |
{n} |
n 是一个非负整数,匹配确定的 n 次。例如:‘o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的两个 o。 |
{n,} |
n 是一个非负整数,至少匹配 n 次。例如:‘o{2,}’ 不能匹配 “Bob” 中的 ‘o’,但能匹配 “foooood” 中的所有 o。‘o{1,}’ 等价于 ‘o+’,‘o{0,}’ 则等价于 ‘o*’。 |
{n, m} |
m 和 n 均为非负整数,其中 n <= m,最少匹配 n 次且最多匹配 m 次。例如:‘o{1,3}’ 将匹配 “fooooood” 中的前三个 o,‘o{0,1}’ 等价于 ‘o?’。请注意在逗号和两个数之间不能有空格。 |
x|y |
匹配 x 或 y。例如,‘z|food’ 能匹配 “z” 或 “food”。‘(z|f)ood’ 则匹配 “zood” 或 “food”。 |
[xyz] |
字符集合,匹配所包含的任意一个字符。例如, ‘[abc]’ 可以匹配 “plain” 中的 ‘a’。 |
[^xyz] |
负值字符集合,匹配未包含的任意字符。例如, ‘[^abc]’ 可以匹配 “plain” 中的’p’。 |
[a-z] |
字符范围,匹配指定范围内的任意字符。例如,‘[a-z]’ 可以匹配 ‘a’ 到 ‘z’ 范围内的任意小写字母字符。 |
[^a-z] |
负值字符范围,匹配任何不在指定范围内的任意字符。例如,‘[^a-z]’ 可以匹配任何不在 ‘a’ 到 ‘z’ 范围内的任意字符。 |
\d |
匹配一个数字字符。等价于 [0-9]。 |
\D |
匹配一个非数字字符。等价于 [^0-9]。 |
\f |
匹配一个换页符。 |
\n |
匹配一个换行符。 |
\r |
匹配一个回车符。 |
\s |
匹配任何空白字符,包括空格、制表符、换页符等等。 |
\S |
匹配任何非空白字符。 |
\t |
匹配一个制表符。 |
\v |
匹配一个垂直制表符。 |
\w |
匹配包括下划线的任何单词字符。等价于’[A-Za-z0-9_]'。 |
\W |
匹配任何非单词字符。 |
常用实例
- 匹配字符
表达式 |
匹配内容 |
示例 |
. |
任意单个字符 |
a.b 可匹配 acb |
\d |
数字 [0-9] |
\d\d 可匹配 12 |
\D |
非数字 [^\d] |
\D 可匹配 a |
\w |
字母、数字、下划线 [a-zA-Z0-9_] |
\w+ 可匹配 abc123 |
\W |
非字母、数字、下划线 |
\W 可匹配 @ |
\s |
空格(包含 \t , \n , \r ) |
\s+ 可匹配 " " |
\S |
非空格字符 |
\S 可匹配 a |
- 量词(重复次数)
表达式 |
匹配次数 |
示例 |
* |
0 次或多次 |
a* 可匹配 "" 、a 、aaaa |
+ |
1 次或多次 |
a+ 可匹配 a 、aaaa |
? |
0 次或 1 次 |
a? 可匹配 "" 、a |
{n} |
恰好 n 次 |
a{3} 可匹配 aaa |
{n,} |
至少 n 次 |
a{2,} 可匹配 aa 、aaaaa |
{n, m} |
n 到 m 次 |
a{2,4} 可匹配 aa 、aaa 、aaaa |
- 边界匹配
表达式 |
匹配位置 |
示例 |
^ |
匹配字符串开头 |
^abc 匹配 "abc123" 但不匹配 "123abc" |
$ |
匹配字符串结尾 |
xyz$ 匹配 "123xyz" 但不匹配 "xyz123" |
\b |
匹配单词边界 |
\bword\b 仅匹配 " word " 而不匹配 "word123" |
\B |
非单词边界 |
\Bword\B 匹配 "awordb" 但不匹配 " word " |
- 分组
表达式 |
作用 |
示例 |
() |
分组 |
(abc)+ 可匹配 "abcabc" |
(?:...) |
非捕获分组 |
(?: abc)+ 仅用于匹配,不保存 |
Java 使用
- 直接使用字符串的 matches() 方法
1 2 3 4 5 6 7 8 9 10 11
| public class RegexDemo { public static void main(String[] args) { String text = "abc123"; boolean isMatch = text.matches("[a-zA-Z]+\\d+"); System.out.println(isMatch); text = "abc123aa"; isMatch = text.matches("[a-zA-Z]+\\d+"); System.out.println(isMatch); } }
|
注意:matches() 方法必须匹配整个字符串,如果只匹配部分,则返回 false。
- 使用 Pattern 和 Matcher
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class RegexExample { public static void main(String[] args) { String text = "My email is test@example.com"; String pattern = "[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+\\.[a-zA-Z]{2,}";
Pattern regex = Pattern.compile(pattern); Matcher matcher = regex.matcher(text);
if (matcher.find()) { System.out.println("匹配的邮箱: " + matcher.group()); } } }
|
使用案例
- 验证邮箱格式
1 2 3 4 5 6
| public static boolean isValidEmail(String email) { String regex = "^[\\w.-]+@[a-zA-Z\\d.-]+\\.[a-zA-Z]{2,6}$"; return email.matches(regex); }
System.out.println(isValidEmail("test@example.com"));
|
- 提取手机号码
1 2 3 4 5 6 7 8 9
| public static void extractPhoneNumbers(String text) { String regex = "\\b1[3-9]\\d{9}\\b"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(text); while (matcher.find()) { System.out.println("手机号: " + matcher.group()); } }
|
- 替换敏感词
1 2 3 4 5 6
| public static String replaceSensitiveWords(String input) { String regex = "(?i)badword|敏感词"; return input.replaceAll(regex, "***"); }
|
- 分割字符串
1 2 3
| String str = "apple,banana,orange"; String[] fruits = str.split("\\s*,\\s*");
|
- 提取 URL 中的域名
1 2 3 4 5 6 7 8 9 10 11
| public static String extractDomain(String url) { String regex = "^(https?://)?([\\w.-]+)(/.*)?$"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(url); if (matcher.find()) { return matcher.group(2); } return null; }
|
- 分组捕获
使用 ()
分组,通过 matcher.group(n)
获取:
1 2 3 4 5 6
| Pattern p = Pattern.compile("(\\d{3})-(\\d{4})"); Matcher m = p.matcher("010-1234"); if (m.matches()) { System.out.println("区号: " + m.group(1)); System.out.println("号码: " + m.group(2)); }
|
修饰符
修饰符 |
含义 |
描述 |
i |
ignore - 不区分大小写 |
将匹配设置为不区分大小写,搜索时不区分大小写:A 和 a 没有区别。 |
g |
global - 全局匹配 |
查找所有的匹配项 |
m |
multiline - 多行匹配 |
使边界字符 ^ 和 $ 匹配每一行的开头和结尾,记住是多行,而不是整个字符串的开头和结尾。 |
s |
特殊字符圆点 . 中包含换行符 \n |
默认情况下的圆点 . 是匹配除换行符 \n 之外的任何字符,加上 s 修饰符之后, .中包含换行符 \n。 |
JS 使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| var str="Google runoob taobao runoob"; var n1=str.match(/runoob/); var n2=str.match(/runoob/g);
var str="Google runoob taobao RUNoob"; var n1=str.match(/runoob/g); var n2=str.match(/runoob/gi);
var str="runoobgoogle\ntaobao\nrunoobweibo"; var n1=str.match(/^runoob/g); var n2=str.match(/^runoob/gm);
var str="google\nrunoob\ntaobao"; var n1=str.match(/google./); var n2=str.match(/runoob./s);
|
Java 使用
修饰符 |
值 |
作用 |
Pattern.CASE_INSENSITIVE |
(?i) |
忽略大小写,如 “hello” 可匹配 “HELLO” |
Pattern.MULTILINE |
(?m) |
多行匹配,^$ 匹配每行的开头和结尾 |
Pattern.DOTALL |
(?s) |
让 . 匹配换行符 \n |
Pattern.UNICODE_CASE |
(?u) |
Unicode 大小写匹配(配合 CASE_INSENSITIVE) |
Pattern.COMMENTS |
(?x) |
忽略正则中的空格和注释 |
Pattern.UNICODE_CHARACTER_CLASS |
(?U) |
使用 Unicode 字符类别 |
- 忽略大小写
1 2 3 4 5 6 7 8 9
| Pattern pattern = Pattern.compile("hello", Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher("HELLO"); System.out.println(matcher.find());
String regex = "(?i)hello"; pattern = Pattern.compile(regex); matcher = pattern.matcher("HELLO"); System.out.println(matcher.find());
|
- 多行匹配
默认 ^
只匹配整个字符串开头,$
只匹配结尾。使用 MULTILINE 后,^
和 $
适用于每行
1 2 3 4 5
| String text = "Hello\nJava"; Pattern pattern = Pattern.compile("^Java", Pattern.MULTILINE);
Matcher matcher = pattern.matcher(text); System.out.println(matcher.find());
|
- 让
.
匹配换行符 \n
默认情况下,.
不会匹配换行符,使用 DOTALL 使 .
能匹配换行符
1 2 3 4 5 6 7
| String text = "Hello\nJava"; Pattern pattern = Pattern.compile("Hello.Java"); System.out.println(pattern.matcher(text).find());
pattern = Pattern.compile("Hello.Java", Pattern.DOTALL);
System.out.println(pattern.matcher(text).find());
|
- 组合多个修饰符
可以使用按位或 |
组合多个修饰符
1 2
| Pattern pattern = Pattern.compile("hello", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
|
运算符优先级
运算符 |
描述 |
\ |
转义符 |
(), (?:), (?=), [] |
圆括号和方括号 |
*, +, ?, {n}, {n,}, {n, m} |
限定符 |
^, $, \任何元字符、任何字符 |
定位点和序列(即:位置和顺序) |
| |
替换,“或” 操作 字符具有高于替换运算符的优先级,使得 “m|food” 匹配 “m” 或 “food”。若要匹配 “mood” 或 “food”,请使用括号创建子表达式,从而产生 “(m|f)ood”。 |