正则表达式(Regular Expression)是一种强大的文本处理工具,用于匹配、查找、替换和验证字符串。下面我将通过实例来讲解正则表达式的基本语法和常见用法。
1. 基本匹配
正则表达式由普通字符(例如字母、数字)和特殊字符(称为元字符)组成。最简单的正则表达式就是普通字符,例如:
-
正则表达式
hello
会匹配字符串中出现的第一个”hello”。
2. 元字符
元字符是正则表达式中具有特殊意义的字符。常见的元字符包括:
-
.
匹配任意单个字符(除了换行符) -
^
匹配字符串的开始 -
$
匹配字符串的结束 -
*
匹配前面的子表达式零次或多次 -
+
匹配前面的子表达式一次或多次 -
?
匹配前面的子表达式零次或一次 -
{n}
匹配前面的子表达式恰好n次 -
{n,}
匹配前面的子表达式至少n次 -
{n,m}
匹配前面的子表达式至少n次,至多m次 -
[]
字符集合,匹配所包含的任意一个字符 -
|
或,匹配两者之一 -
()
分组,将多个字符组合成一个单元,并可捕获匹配的文本
3. 转义
如果你想要匹配元字符本身,需要使用反斜杠\
进行转义。例如,匹配点号.
,需要使用\.
。
4. 字符类
用方括号[]
表示,匹配括号内的任意一个字符。
-
[abc]
匹配a、b或c -
[a-z]
匹配任意小写字母 -
[0-9]
匹配任意数字 -
[^abc]
匹配除了a、b、c之外的任意字符(在字符类中的^
表示否定)
5. 预定义字符类
-
\d
匹配数字,等价于[0-9]
-
\D
匹配非数字,等价于[^0-9]
-
\w
匹配字母、数字、下划线,等价于[A-Za-z0-9_]
-
\W
匹配非字母、数字、下划线 -
\s
匹配空白字符(空格、制表符、换行符等) -
\S
匹配非空白字符
6. 实例
实例1:匹配邮箱地址
假设我们要匹配一个简单的邮箱地址,格式为:用户名@域名.后缀
-
用户名:可以包含字母、数字、点、下划线、减号,且不能以点开头或结尾,不能连续两个点。
-
域名:可以包含字母、数字、减号,且不能以减号开头或结尾。
-
后缀:一般为2-5个字母。
正则表达式:^[a-zA-Z0-9]+([._-]?[a-zA-Z0-9]+)*@[a-zA-Z0-9]+(-?[a-zA-Z0-9]+)*(\.[a-zA-Z]{2,5})+$
解释:
-
^
表示字符串开始 -
[a-zA-Z0-9]+
至少一个字母或数字开头 -
([._-]?[a-zA-Z0-9]+)*
接下来可以是零个或多个以下结构:一个可选的点、下划线或减号,然后至少一个字母或数字。注意这里我们使用了?
表示前面的字符可选,这样允许中间有点、下划线或减号,但不会连续两个点。 -
@
匹配字面量@ -
[a-zA-Z0-9]+
域名部分以至少一个字母或数字开头 -
(-?[a-zA-Z0-9]+)*
之后可以跟零个或多个:一个可选的减号然后至少一个字母或数字,这样确保域名中可以有减号但不能连续减号或开头结尾有减号。 -
(\.[a-zA-Z]{2,5})+
匹配一个点后跟2到5个字母,这个整体可以出现一次或多次(例如:.com、.co.uk) -
$
字符串结束
注意:这只是一个简单的示例,实际邮箱地址更复杂,此表达式可能不覆盖所有情况。
实例2:匹配URL
假设我们要匹配HTTP/HTTPS的URL。
正则表达式:^https?://[^\s/$.?#].[^\s]*$
解释:
-
^https?
匹配http或https,s可选 -
://
匹配字面量 -
[^\s/$.?#]
匹配一个不是空白字符、不是/、$、.、?、#的字符,确保域名部分不以这些字符开头 -
[^\s]*
匹配任意非空白字符,直到字符串结束
实例3:匹配日期(YYYY-MM-DD)
正则表达式:^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$
解释:
-
^\d{4}
匹配4位数字的年份 -
-
匹配字面量减号 -
(0[1-9]|1[0-2])
匹配月份,01-09或10-12 -
-
匹配字面量减号 -
(0[1-9]|[12][0-9]|3[01])
匹配日期,01-09、10-29、30-31
实例4:匹配手机号码(以中国手机为例)
中国手机号码:1开头,第二位是3-9,后面9位数字。
正则表达式:^1[3-9]\d{9}$
实例5:替换HTML标签
如果我们想移除字符串中所有的HTML标签,可以使用替换功能,将匹配到的标签替换为空字符串。
正则表达式:<[^>]+>
解释:匹配以<
开头,后面跟着一个或多个不是>
的字符,然后以>
结尾。
基本语法
1. 字面量匹配
hello # 匹配 "hello" test123 # 匹配 "test123"
2. 特殊字符转义
\. # 匹配点号字符 \\ # 匹配反斜杠 \$ # 匹配美元符号
常用元字符
元字符 | 说明 | 示例 |
---|---|---|
. |
匹配任意单个字符 | a.c 匹配 “abc”, “a c”, “a-c” |
^ |
匹配字符串开始 | ^Hello 匹配以 “Hello” 开头的字符串 |
$ |
匹配字符串结束 | end$ 匹配以 “end” 结尾的字符串 |
\d |
匹配数字 | \d\d 匹配 “12”, “45” 等 |
\w |
匹配字母、数字、下划线 | \w+ 匹配单词 |
\s |
匹配空白字符 | \s+ 匹配空格、制表符等 |
量词
量词 | 说明 | 示例 |
---|---|---|
* |
0次或多次 | ab*c 匹配 “ac”, “abc”, “abbc” |
+ |
1次或多次 | ab+c 匹配 “abc”, “abbc” |
? |
0次或1次 | colou?r 匹配 “color” 或 “colour” |
{n} |
恰好n次 | a{3} 匹配 “aaa” |
{n,} |
至少n次 | a{2,} 匹配 “aa”, “aaa” 等 |
{n,m} |
n到m次 | a{2,4} 匹配 “aa”, “aaa”, “aaaa” |
字符类
1. 自定义字符类
[aeiou] # 匹配任意元音字母 [0-9] # 匹配任意数字 [a-zA-Z] # 匹配任意字母
2. 排除字符类
[^aeiou] # 匹配非元音字母 [^0-9] # 匹配非数字字符
分组和捕获
1. 基本分组
(abc)+ # 匹配 "abc", "abcabc" 等
2. 非捕获分组
(?:abc)+ # 匹配但不捕获分组
3. 命名捕获组
(?<year>\d{4})-(?<month>\d{2}) # 命名捕获年月
实际应用示例
1. 邮箱验证
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
示例匹配:
2. 手机号码验证
^1[3-9]\d{9}$
示例匹配:
-
13812345678
-
15987654321
3. URL 提取
https?://[^\s/$.?#].[^\s]*
示例匹配:
4. 日期匹配
\d{4}-\d{2}-\d{2}
示例匹配:
-
2023-12-25
-
1990-01-01
5. HTML 标签提取
<([a-z][a-z0-9]*)[^>]*>(.*?)</\1>
示例匹配:
-
<div>内容</div>
-
<p class="text">段落</p>
6. 密码强度验证
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$
要求:
-
至少8个字符
-
包含大小写字母
-
包含数字
-
包含特殊字符
不同语言中的使用
Python 示例
# 匹配邮箱 pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' email = "user@example.com" if re.match(pattern, email): print("邮箱格式正确") # 提取所有数字 text = "价格是123元,重量是45公斤" numbers = re.findall(r'\d+', text) print(numbers) # ['123', '45']
JavaScript 示例
// 验证手机号码 const phonePattern = /^1[3-9]\d{9}$/; const phone = "13812345678"; if (phonePattern.test(phone)) { console.log("手机号码格式正确"); } // 替换文本 const text = "今天是2023-12-25"; const newText = text.replace(/(\d{4})-(\d{2})-(\d{2})/, "$1年$2月$3日"); console.log(newText); // "今天是2023年12月25日"
Java 示例
import java.util.regex.*; public class RegexExample { public static void main(String[] args) { // 验证邮箱 String emailPattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"; String email = "user@example.com"; if (email.matches(emailPattern)) { System.out.println("邮箱格式正确"); } // 提取URL String text = "访问 https://example.com 获取更多信息"; Pattern urlPattern = Pattern.compile("https?://[^\\s/$.?#].[^\\s]*"); Matcher matcher = urlPattern.matcher(text); while (matcher.find()) { System.out.println("找到URL: " + matcher.group()); } } }
实用技巧
-
使用在线测试工具:如 regex101.com 测试和调试正则表达式
-
注释复杂表达式:使用
(?#注释)
或x
模式添加注释 -
性能优化:避免过度使用回溯,尽量使用具体字符类
-
测试边界情况:确保正则表达式处理各种边界情况
这个教程涵盖了正则表达式的基础知识和常见应用场景。建议在实际使用中多加练习,逐步掌握这个强大的文本处理工具!