一、正则表达式简介
1. 什么是正则表达式?
正则表达式(Regular Expression,简称regex或regexp)是一种用于描述搜索模式的特殊字符序列。它可以用于查找、替换或验证文本中的特定模式。正则表达式广泛应用于字符串匹配和文本处理领域,如数据验证、信息抽取和文本编辑等。
2. 常见应用场景
正则表达式在日常编程中有着广泛的应用,例如:
- 验证用户输入(如邮箱地址、电话号码)
- 数据清洗和格式化
- 从日志文件中提取有用信息
- 搜索和替换文本
二、正则表达式的基础构成
1. 普通字符
普通字符是指没有特殊含义的字符,它们在正则表达式中直接表示自身。例如:
a匹配字符'a'1匹配字符'1'.匹配字符'.'
2. 元字符
元字符是有特殊意义的字符,用于构建复杂的模式。常见的元字符包括:
.:匹配除换行符以外的任意单个字符。^:匹配字符串的开始位置。$:匹配字符串的结束位置。*:匹配前面的元素零次或多次。+:匹配前面的元素一次或多次。?:匹配前面的元素零次或一次。|:表示“或”,匹配左右两边的任意一个表达式。():用于分组,组合多个表达式。[]:表示字符类,匹配方括号中的任意一个字符。
3. 字符类
字符类是用来定义一个字符集合,用方括号括起来。字符类中的每个字符都可以被匹配。常见的字符类有:
[abc]:匹配'a'、'b'或'c'中的任意一个字符。[0-9]:匹配'0'到'9'之间的任意一个数字。[^abc]:匹配除'a'、'b'、'c'之外的任意字符。
4. 量词
量词用于指定前面的元素可以重复的次数。常见的量词包括:
*:匹配前面的元素零次或多次。+:匹配前面的元素一次或多次。?:匹配前面的元素零次或一次。{n}:匹配前面的元素恰好n次。{n,}:匹配前面的元素至少n次。{n,m}:匹配前面的元素至少n次,至多m次。
5. 边界匹配
边界匹配符用于指定匹配的开始或结束位置:
^:匹配字符串的开头。$:匹配字符串的结尾。\b:匹配单词边界。\B:匹配非单词边界。
6. 分组和捕获
分组是将正则表达式的多个部分组合起来,使它们作为一个整体进行匹配。分组使用小括号 () 来表示。
(abc):将'abc'作为一个整体进行匹配。(\d{3}):将三位数字作为一个整体进行匹配。
分组还可以用于捕获匹配的内容,捕获的内容可以在后续使用。
7. 转义字符
由于某些字符在正则表达式中具有特殊含义,如果要匹配这些字符本身,需要使用反斜杠 \ 进行转义。例如:
\.:匹配.字符,而不是作为任意字符的通配符。\*:匹配*字符,而不是作为量词。
三、正则表达式的高级特性
1. 非捕获组
在使用捕获组 () 时,正则表达式会保存匹配的内容,有时这并不是我们想要的。如果你只想分组但不捕获,可以使用非捕获组 (?:...):
(?:abc):匹配abc,但不会捕获该内容。
2. 回溯引用
回溯引用允许你在正则表达式中引用之前捕获的内容。可以通过反斜杠 \ 和数字来使用回溯引用:
(abc)\1:匹配abcabc,\1引用第一个捕获组的内容。(.)\1:匹配两个连续的相同字符,如aa、bb。
3. 正向先行断言 (Lookahead)
正向先行断言用于检查某个子字符串是否在另一个字符串的前面,但不包括在最终的匹配中。用法是 (?=...):
\d(?=px):匹配跟在px前面的数字,但不包含px。\w+(?=\s):匹配后面跟着空白字符的单词,但不包括空白字符。
4. 负向先行断言 (Negative Lookahead)
负向先行断言用于确保某个子字符串不出现在另一个字符串的前面。用法是 (?!...):
\d(?!px):匹配跟在非px前面的数字。\w+(?!s):匹配后面不跟空白字符的单词。
5. 正向后发断言 (Lookbehind)
正向后发断言用于检查某个子字符串是否在另一个字符串的后面,但不包括在最终的匹配中。用法是 (?<=...):
(?<=\$)\d+:匹配跟在美元符号$后面的数字,但不包括$。(?<=\bword\s)\w+:匹配跟在单词word后面的单词,但不包括word。
6. 负向后发断言 (Negative Lookbehind)
负向后发断言用于确保某个子字符串不出现在另一个字符串的后面。用法是 (?<!...):
(?<!\$)\d+:匹配不跟在美元符号$后面的数字。(?<!\bword\s)\w+:匹配不跟在单词word后面的单词。
7. 贪婪与懒惰匹配
默认情况下,量词是贪婪的,会匹配尽可能多的字符。可以通过在量词后加 ? 使其变为懒惰模式,即尽可能少地匹配。
.*:贪婪匹配,匹配尽可能多的字符。.*?:懒惰匹配,匹配尽可能少的字符。
8. 嵌入条件 (Conditionals)
某些正则表达式引擎支持条件匹配。语法是 (?(条件)真分支|假分支):
(?(1)abc|def):如果第一个捕获组匹配成功,则匹配abc,否则匹配def。
9. 递归匹配
递归匹配用于匹配嵌套的模式,如匹配平衡的括号。并非所有正则表达式引擎都支持此功能,语法因引擎而异:
(\((?:[^()]|(?R))*\)):在支持递归的引擎中,用于匹配平衡的括号。
10. 注释
在某些正则表达式引擎中,可以通过 (?x) 启用忽略空白和注释模式,从而使正则表达式更具可读性:
(?x) \d+ \s* # 匹配一个或多个数字,然后是零个或多个空白。
11. 命名捕获组
命名捕获组允许你为捕获的子字符串命名,以便在后续处理中更方便地引用。语法为 (?<name>...):
(?<area_code>\d{3}):匹配三位数字,并将其命名为area_code。
12. 条件判断 (Conditional Expressions)
在一些高级正则表达式引擎中,允许使用条件表达式来选择不同的模式进行匹配。语法为 (?(id/name)yes-pattern|no-pattern):
(?(1)abc|def):如果捕获组 1 存在,则匹配abc,否则匹配def。
四、常见正则表达式
1. 邮箱地址验证:
^[\w\.-]+@[a-zA-Z\d\.-]+\.[a-zA-Z]{2,6}$
2. 手机号码验证(中国):
^1[3-9]\d{9}$
3. IP地址验证(IPv4):
^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$
4. 邮政编码验证(中国):
^\d{6}$
5. 日期格式验证(YYYY-MM-DD):
^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
6. URL验证:
^https?:\/\/[^\s/$.?#].[^\s]*$
7. 密码强度验证(至少8位,包括字母、数字、特殊字符):
^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$
8. HTML标签匹配:
<(\/?[\w\s]*)(\s*[^>]*)>
9. 匹配含有至少一个数字的字符串:
\d+
10. 去除字符串首尾空白:
^\s+|\s+$