Qwen2.5-7B-Instruct实战案例:用自然语言生成正则表达式+测试用例+边界说明

你是不是也遇到过这种情况?产品经理提了个需求:“帮我写个正则,能匹配所有手机号,但排除掉测试号段186开头的。” 你心里一咯噔,正则表达式这玩意儿,语法像天书,写起来费劲,调试起来更费劲。好不容易写出来,还得绞尽脑汁想各种边界情况去测试。

现在,有了Qwen2.5-7B-Instruct,这个痛点可以轻松解决了。这个7B参数的“大块头”模型,逻辑推理和代码能力远超轻量版,让它来当你的“正则表达式私人助理”,再合适不过。今天,我就带你看看,如何用自然语言,让这个AI助手帮你一站式搞定正则表达式的生成、测试和边界说明。

1. 为什么需要AI来写正则?

在深入实战之前,我们先聊聊为什么这件事值得做。正则表达式是程序员和数据分析师的利器,但它的学习曲线陡峭,语法晦涩难懂。

传统写正则的流程通常是这样的:

  1. 需求模糊:产品或业务方用自然语言描述匹配规则。
  2. 手动翻译:开发者将自然语言“翻译”成正则语法,这个过程极易出错。
  3. 反复调试:写个简单的测试脚本,用几个例子跑一下,发现不对再回去改正则。
  4. 遗漏边界:往往只测试了正常情况,一些奇怪的边界情况(如空字符串、超长输入、特殊字符)容易被忽略,为线上问题埋下隐患。

整个过程耗时耗力,而且对经验依赖很大。

而用Qwen2.5-7B-Instruct之后,流程变成了这样:

  1. 自然语言描述:你直接用大白话把需求告诉AI。
  2. 一键生成:AI瞬间返回正则表达式,并附上清晰的解释。
  3. 附带测试:AI同时提供覆盖各种情况的测试用例。
  4. 边界预警:AI会主动指出这个正则可能处理不了的边界情况。

从“人适应机器语法”变成了“机器理解人的意图”,效率和可靠性都大大提升。接下来,我们就启动服务,开始实战。

2. 环境准备与快速启动

首先,你需要一个已经部署好的Qwen2.5-7B-Instruct服务。如果你用的是基于Streamlit的镜像,启动非常简单。

启动服务:

  1. 找到并运行项目主程序(通常是 app.pystreamlit run app.py)。
  2. 首次启动需要加载7B模型,耐心等待20-40秒,控制台会显示加载进度。
  3. 看到宽屏聊天界面在浏览器中打开,就意味着服务启动成功了。

界面初览: 启动后,你会看到一个清爽的宽屏界面。左侧是控制台,有两个关键滑块:

  • 温度(创造力):建议保持默认的0.7,这样AI的回答在准确性和创造性上有很好的平衡。
  • 最大回复长度:对于生成正则和代码的场景,可以调到1024或更高,确保回复完整。

右侧就是我们的主聊天区域了。一切就绪,让我们开始第一个任务。

3. 实战案例一:生成一个复杂的正则表达式

我们从一个相对复杂的需求开始,看看Qwen2.5-7B-Instruct如何应对。

我的需求是: “写一个Python的正则表达式,用来匹配中国大陆的手机号码。规则是:以1开头,第二位是3、4、5、6、7、8、9中的一个,总共11位数字。但是,需要能识别出号码中的运营商:移动(134-139, 147, 150-152, 157-159, 165, 172, 178, 182-184, 187-188, 198)、联通(130-132, 145, 155-156, 166, 171, 175-176, 185-186)、电信(133, 149, 153, 162, 173-174, 177, 180-181, 189, 190, 191, 193, 199)。最后,这个正则要能方便地提取出号段(前三位)和剩余号码。”

我把这段话直接输入到聊天框,点击发送。很快,AI给出了回复。

AI生成的代码与解释:

import re

# 综合匹配中国大陆手机号并识别运营商的正则表达式
pattern = r'^(1(3[0-9]|4[5-9]|5[0-9]|6[0-9]|7[0-9]|8[0-9]|9[0-9])\d{8})$'

# 为了清晰识别运营商,我们使用命名捕获组来分别匹配不同运营商号段
phone_regex = re.compile(r‘^(?P<all>(?P<prefix>1(3[4-9]|47|5[0-2]|5[7-9]|65|72|78|8[2-4]|8[7-8]|98)|1(3[0-2]|45|5[5-6]|66|71|7[5-6]|8[5-6])|1(33|49|53|62|7[3-4]|77|8[0-1]|89|90|91|93|99))\d{8})$’)

def parse_phone_number(phone_str):
    """
    解析手机号码,返回运营商信息和分段号码。
    """
    match = phone_regex.match(phone_str)
    if not match:
        return None

    full_number = match.group(‘all’)
    prefix = match.group(‘prefix’)

    # 根据前缀判断运营商
    if prefix.startswith(('134', '135', '136', '137', '138', '139', '147', '150', '151', '152', '157', '158', '159', '165', '172', '178', '182', '183', '184', '187', '188', '198')):
        carrier = “中国移动”
    elif prefix.startswith(('130', '131', '132', '145', '155', '156', '166', '171', '175', '176', '185', '186')):
        carrier = “中国联通”
    elif prefix.startswith(('133', '149', '153', '162', '173', '174', '177', '180', '181', '189', '190', '191', '193', '199')):
        carrier = “中国电信”
    else:
        carrier = “未知运营商”

    return {
        “full_number”: full_number,
        “prefix”: prefix,
        “remaining”: full_number[3:], # 第4位到第11位
        “carrier”: carrier
    }

# 测试用例
test_numbers = [
    “13800138000”, # 移动
    “18612345678”, # 联通
    “18987654321”, # 电信
    “12345678901”, # 非法第二位
    “1380013800”,  # 少于11位
    “138001380001”, # 多于11位
    “” # 空字符串
]

print(“测试结果:”)
for num in test_numbers:
    result = parse_phone_number(num)
    if result:
        print(f“号码 {num} -> 运营商: {result[‘carrier’]}, 号段: {result[‘prefix’]}, 剩余号码: {result[‘remaining’]}”)
    else:
        print(f“号码 {num} -> 匹配失败”)

AI提供的核心解释:

  1. 正则核心^1(3[0-9]|4[5-9]|5[0-9]|6[0-9]|7[0-9]|8[0-9]|9[0-9])\d{8}$ 确保了1开头、第二位合法、总长11位的基本规则。
  2. 运营商识别:它没有用一个巨长无比的正则直接匹配所有号段,而是巧妙地用了命名捕获组(?P<prefix>...)先提取出前三位,然后在Python代码里用 startswith() 判断运营商。这样正则更清晰,代码也更易维护。
  3. 结构化返回:函数直接返回一个字典,包含完整号码、号段、剩余号码和运营商,开箱即用。

同时,AI还附上了测试用例和边界说明:

  • 正常用例:包含了移动、联通、电信的典型号码。
  • 异常用例:第二位非法的号码、长度不对的号码。
  • 边界情况:空字符串。AI特别指出,正则开头的^和结尾的$确保了必须完整匹配11位,空字符串自然匹配失败,符合预期。

这个回复不仅给了代码,还给了思路和验证方法,直接复制粘贴就能跑起来测试,非常贴心。

4. 实战案例二:从测试用例反推正则规则

有时候,我们手头只有一些正例和反例,需要反推出正则规则。这对AI的逻辑推理能力要求更高。

我这样问AI: “我这里有一些字符串,符合规则的包括:‘user_123’, ‘item-456’, ‘test_789-abc’。不符合规则的包括:‘123user’, ‘user@name’, ‘ab’, ‘averylongstringthatisnotvalid’。请帮我分析规则,并写出一个能匹配所有符合规则字符串的Python正则表达式。”

AI的分析与生成:

AI没有直接写正则,而是先给出了它的推理过程: “让我们先分析符合和不符合的字符串,找出模式: 符合的:user_123 (字母,下划线,数字), item-456 (字母,连字符,数字), test_789-abc (字母,下划线,数字,连字符,字母)。 不符合的:123user (以数字开头), user@name (包含@符号), ab (太短,且只有字母), averylongstringthatisnotvalid (可能过长或包含空格?实际上它全是字母,可能规则要求必须有数字或特定分隔符)。

推测规则可能是:

  1. 必须以字母开头。
  2. 只能包含字母、数字、下划线(_)和连字符(-)。
  3. 必须至少包含一个数字。
  4. 长度可能有一定范围?从‘ab’被排除看,可能要求长度>=3。从长字符串被排除看,可能长度有上限,或者它被排除是因为不含数字(推测3更可能)。

先基于前三点写正则:^[a-zA-Z][a-zA-Z0-9_-]*\d[a-zA-Z0-9_-]*$。这个规则要求至少一个数字,且字母开头。”

然后,它给出了优化后的正则和测试代码:

import re

# 根据分析编写的正则表达式
# 规则:字母开头,仅包含字母数字下划线连字符,且必须至少包含一个数字。
pattern = r‘^[a-zA-Z][a-zA-Z0-9_-]*\d[a-zA-Z0-9_-]*$’
regex = re.compile(pattern)

test_strings = [
    “user_123”, # 符合
    “item-456”, # 符合
    “test_789-abc”, # 符合
    “123user”, # 不符合:数字开头
    “user@name”, # 不符合:包含@
    “ab”, # 不符合:无数字
    “averylongstringthatisnotvalid”, # 不符合:无数字
    “Valid_1”, # 新增:符合
    “A-2-b”, # 新增:符合
    “noNumberHere”, # 新增:不符合
]

print(“测试反推规则的正则:”)
for s in test_strings:
    match = regex.match(s)
    print(f“{s:30} -> {‘匹配成功’ if match else ‘匹配失败’}”)

AI的总结与边界提醒: “这个正则满足了已给示例。但需要注意:

  • 没有限制长度。如果原规则有长度限制(比如3-20个字符),需要修改为 ^[a-zA-Z][a-zA-Z0-9_-]{2,19}\d[a-zA-Z0-9_-]*$ 并不准确,因为数字位置不定。更稳妥的是匹配后再检查长度。
  • 要求至少一个数字。如果‘ab’是因为长度而非数字被排除,那么规则可能不同。 建议用更多测试用例验证,特别是边界情况,如空串、非常长的串、纯数字串等。”

这个案例展示了AI强大的归纳和推理能力。它不只是模式匹配,而是在分析正反例后,主动提出对潜在规则的假设,并指出当前方案的局限性,提醒我需要更多信息来确认。这就像一个经验丰富的同事在和你一起讨论需求。

5. 实战案例三:生成正则并附带完整测试套件

对于要上生产环境的代码,一个健壮的正则表达式必须配有完整的测试。我们可以让AI一次性完成。

我的指令: “为‘提取字符串中所有符合‘YYYY-MM-DD’格式的日期’这个需求,写一个Python正则表达式。请同时生成一个完整的pytest测试套件,覆盖以下情况:1. 标准日期(如‘2023-10-01’)。2. 月份和日期为个位数时带前导零和不带前导零的情况(如‘2023-9-5’)。3. 非法日期(如‘2023-13-01’, ‘2023-02-30’)。4. 字符串中包含多个日期。5. 字符串中混入其他类似格式但不是日期的内容(如‘2023-10-001’)。最后,请指出这个简单正则的局限性。”

AI的一站式输出:

import re
from datetime import datetime

def extract_dates(text):
    """
    使用正则表达式提取YYYY-MM-DD格式的日期。
    注意:此正则只做格式校验,不保证日期真实存在。
    """
    # 正则表达式:YYYY-MM-DD,月份01-12,日期01-31
    date_pattern = re.compile(r‘\b(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])\b’)
    matches = date_pattern.findall(text)
    # 将匹配的元组转换为字符串列表
    return [‘-’.join(match) for match in matches]

# 示例使用
sample_text = “项目开始于2023-09-01,结束于2024-1-15。中间有个错误日期2023-13-45。另一个日期是2023-02-28。”
print(“提取到的日期:”, extract_dates(sample_text))

紧接着,AI生成了详细的pytest测试套件:

# test_date_extractor.py
import pytest
from your_module import extract_dates # 假设上面的函数保存在your_module.py

def test_standard_date():
    assert extract_dates(“今天是2023-10-01。”) == [“2023-10-01”]

def test_single_digit_month_day():
    # 注意:正则要求两位数字,所以‘2023-9-5’不会被匹配
    assert extract_dates(“日期2023-09-05和2023-10-1。”) == [“2023-09-05”] # ‘2023-10-1’不匹配
    # 如果需要匹配单数字,正则应改为 r‘\b(\d{4})-(\d{1,2})-(\d{1,2})\b’,但这里按原需求。

def test_invalid_numeric_range():
    # 正则只检查数字范围,不检查日期有效性,所以‘2023-13-01’(月份13)不匹配,但‘2023-02-30’(2月30日)会匹配!
    assert extract_dates(“无效月2023-13-01。”) == []
    assert extract_dates(“无效日2023-02-30。”) == [“2023-02-30”] # 这是此正则的缺陷!

def test_multiple_dates():
    assert extract_dates(“从2023-01-01到2023-12-31。”) == [“2023-01-01”, “2023-12-31”]

def test_mixed_content():
    assert extract_dates(“编号2023-10-001不是日期,2023-10-01才是。”) == [“2023-10-01”]

def test_no_dates():
    assert extract_dates(“这里没有日期。”) == []

def test_date_like_patterns():
    assert extract_dates(“电话是1234-56-7890。”) == [] # 被\b单词边界限制,可能不匹配,取决于上下文。

if __name__ == “__main__”:
    pytest.main([“-v”, __file__])

最后,AI清晰地列出了该正则的局限性:

  1. 有效性验证不足:最大的问题是它无法验证日期是否真实存在(如2023-02-30、2023-11-31)。在生产环境中,提取后必须用 datetime.strptime() 或类似库进行验证。
  2. 格式僵化:它要求月份和日期必须是两位数字(带前导零),2023-9-5 这种格式无法匹配。如果需要更灵活,正则会变复杂。
  3. 单词边界依赖\b 在有些上下文(如紧跟标点)下可能工作不如预期。
  4. 性能考虑:对于极端长的文本,复杂的正则可能有效率问题,但本例中问题不大。

AI不仅完成了代码和测试,还主动“踩坑”,指出了测试用例中暴露出的正则缺陷(匹配了2月30日),并给出了下一步的改进方向。这相当于一份高质量的开发文档和测试报告。

6. 总结与最佳实践建议

通过上面三个案例,我们可以看到,将Qwen2.5-7B-Instruct作为“正则表达式助手”能极大提升效率。它把我们从繁琐的语法记忆和碎片化的调试中解放出来。

回顾一下它的核心优势:

  • 自然语言交互:直接用说话的方式提需求,无需记忆复杂语法。
  • 逻辑推理能力强:能分析示例、推测规则,甚至发现你需求中潜在的矛盾点。
  • 输出结果即用:提供的代码通常结构清晰,附带解释和测试用例,质量很高。
  • 考虑边界情况:会主动指出生成的正则的局限性,提醒你注意验证。

在使用过程中,我也总结出一些最佳实践,能让它更好地为你服务:

  1. 需求描述要具体:越具体,生成的结果越精准。比如,不说“匹配邮箱”,而说“匹配常见的互联网邮箱格式,包含@和点,且域名部分至少有两个字母”。
  2. 提供正反示例:像案例二那样,提供“应该匹配”和“不应该匹配”的例子,能极大帮助AI理解你的真实意图。
  3. 明确编程语言和上下文:开头就说明是Python、JavaScript还是其他语言的正则,因为语法略有不同。如果正则是在特定函数或环境中使用,也一并说明。
  4. 利用多轮对话深化:不要指望一次成功。如果第一版正则不完美,可以把测试结果反馈给AI,比如“这个正则匹配了‘2023-02-30’,但我希望排除无效日期,该怎么修改?” 它能基于上下文进行迭代优化。
  5. 始终进行人工复核与测试:AI非常强大,但它不是神。对于核心业务逻辑或安全相关的正则(如输入验证),一定要用更全面的测试用例进行最终验证,特别是它提到的那些边界情况。

总而言之,Qwen2.5-7B-Instruct的出现,让处理正则表达式这类“精确但繁琐”的任务,变得像和一个聪明的同事结对编程一样轻松。它负责将模糊的需求转化为精确的语法和代码,而你则专注于更高层的逻辑和业务规则。下次再遇到正则难题,不妨让它来试试。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐