1. 语言模型和数据库-正则表达式2025-06-20

  1. p216 正则表达式

一、基础语法:字符与规则

1. 普通字符

  • 直接匹配自身,比如 abc 会精准匹配字符串里的 "abc" 子串,像在 "xyzabc123" 里,abc 就能匹配到中间的 "abc"

2. 元字符(核心规则)

元字符 含义 & 示例
. 匹配除换行符(\n 等)外任意单个字符。例:a.c 可匹配 "abc""a&c",但不匹配 "a\nc"
[] 匹配方括号内任意单个字符。例:[abc] 匹配 "a"/"b"/"c"[a-z] 匹配任意小写字母(范围)
[^] 匹配不在方括号内的任意单个字符(取反)。例:[^0-9] 匹配非数字字符,像字母、符号等
\d 等价于 [0-9],匹配数字
\D 等价于 [^0-9],匹配非数字
\w 等价于 [a-zA-Z0-9_],匹配字母、数字、下划线(“单词字符”)
\W 等价于 [^a-zA-Z0-9_],匹配非单词字符(如符号 !@# 等)
\s 匹配空白字符(空格、制表符 \t、换行符 \n 等)
\S 匹配非空白字符
^ 匹配字符串的开头位置(多行模式下也匹配行首)。例:^abc 只匹配字符串以 "abc" 开头的部分
$ 匹配字符串的结尾位置(多行模式下也匹配行尾)。例:abc$ 只匹配字符串以 "abc" 结尾的部分
| 逻辑“或”,匹配左边或右边的子模式。例:abc|123 匹配 "abc""123"
() 分组,把多个字符当一个整体匹配,也用于捕获匹配结果(提取子串)。例:(abc)+ 匹配连续的 "abcabc"
* 匹配前面的子模式 0 次或多次(尽可能多匹配,“贪婪模式”)。例:a* 匹配 ""(空)、"a""aa"
+ 匹配前面的子模式 1 次或多次(贪婪)。例:a+ 匹配 "a""aa",但不匹配 ""
? 有两种用法:
1. 匹配前面的子模式 0 次或 1 次(可选),例:a? 匹配 """a"
2. 跟在 */+ 后,开启非贪婪模式(尽可能少匹配),例:a+? 匹配到单个 "a" 就停止
{n} 匹配前面的子模式恰好 n 次。例:a{3} 匹配 "aaa"
{n,} 匹配前面的子模式至少 n 次(贪婪)。例:a{2,} 匹配 "aa""aaa"
{n,m} 匹配前面的子模式 n 到 m 次(贪婪)。例:a{1,3} 匹配 "a""aa""aaa"

二、常见场景示例

1. 验证字符串格式(如邮箱、手机号)

  • 验证邮箱(简单版,实际更复杂):

    ^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$
    

    解释:

    • ^ 开头,$ 结尾 → 匹配完整字符串;
    • [a-zA-Z0-9_.+-]+ → 匹配邮箱用户名(字母、数字、_/./+/- 等);
    • @ → 固定符号;
    • [a-zA-Z0-9-]+ → 匹配域名(如 gmailbaidu );
    • \. → 转义 .(因为 . 本身是元字符,需匹配实际点号);
    • [a-zA-Z0-9-.]+ → 匹配后缀(如 comcnco.uk )。
  • 验证手机号(以中国大陆手机号为例):

    ^1[3-9]\d{9}$
    

    解释:

    • ^1 → 以 1 开头;
    • [3-9] → 第二位是 3 - 9 的数字;
    • \d{9} → 后面跟 9 位数字;
    • $ → 结尾,确保整体是 11 位手机号。

2. 提取关键信息(如从日志里抓 ID)

假设日志格式是:[INFO] 2024-10-01 12:00:00 - user_id=12345, action=login
想提取 user_id 的值,可用 regex:

user_id=(\d+)
  • user_id= → 匹配固定文本;
  • (\d+) → 分组捕获数字(\d+ 匹配 1 个及以上数字),提取结果就是 12345

3. 替换文本(如清理非法字符)

把字符串里的“非字母、数字、下划线”替换成空格,可用:

import re
text = "hello!@# world_123"
new_text = re.sub(r'[^a-zA-Z0-9_]', ' ', text)
# new_text 结果: "hello   world_123"(!@# 被换成空格)
  • re.sub() 是 Python re 模块的替换函数;
  • [^a-zA-Z0-9_] → 匹配非字母、数字、下划线的字符;
  • 第二个参数 ' ' 表示用空格替换匹配到的内容。

三、Python 中使用正则(re 模块核心用法)

Python 通过 re 模块实现正则功能,常用方法:

1. re.match(pattern, string)

  • 尝试从字符串开头匹配 pattern,匹配到返回 Match 对象,否则返回 None
  • 示例:
    import re
    result = re.match(r'abc', 'abcdef')
    if result:
        print(result.group())  # 输出: abc(匹配到的内容)
    

2. re.search(pattern, string)

  • 扫描整个字符串,找第一个匹配的子串,返回 Match 对象或 None
  • 示例:
    result = re.search(r'\d+', 'abc123def456')
    if result:
        print(result.group())  # 输出: 123(第一个数字串)
    

3. re.findall(pattern, string)

  • 找到所有匹配的子串,返回列表(若有分组,返回分组内容列表)。
  • 示例:
    result = re.findall(r'\d+', 'abc123def456')
    print(result)  # 输出: ['123', '456']
    

4. re.sub(pattern, repl, string, count=0)

  • 替换匹配的子串,repl 可以是字符串或函数;count 控制替换次数(0 表示全部替换)。
  • 示例(替换所有数字为 # ):
    new_text = re.sub(r'\d+', '#', 'abc123def456')
    print(new_text)  # 输出: abc#def#
    

5. re.compile(pattern)

  • 预编译正则表达式,提升重复匹配效率(频繁用同个 pattern 时推荐)。
  • 示例:
    pattern = re.compile(r'\d+')
    result1 = pattern.findall('abc123')
    result2 = pattern.findall('def456')
    print(result1, result2)  # 输出: ['123'] ['456']
    

四、写正则的小技巧

  1. 先拆分需求:把复杂匹配拆成小规则(如邮箱拆成“用户名 + @ + 域名 + 后缀” )。
  2. 巧用在线工具调试:像 Regex101 ,输入 pattern 和测试文本,实时看匹配结果,还能解释正则含义,超方便~
  3. 注意贪婪/非贪婪*/+ 默认贪婪(尽可能多匹配),加 ? 可转非贪婪(a+? 匹配到单个 a 就停),处理多行、短文本时容易踩坑,需留意。

正则表达式乍看复杂,但记住常用元字符含义,结合场景练习(比如验证自己的手机号、邮箱格式 ),很快就能上手啦!遇到复杂需求,分步拆解 + 在线调试,基本都能搞定~

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容