正则表达式手册
正则表达式手册

一、正则表达式简介

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:匹配两个连续的相同字符,如 aabb

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+$