You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多行正则匹配:匹配至下一组出现时停止的技术问题

解决许可证文件中分组匹配到下一组停止的问题

看起来你已经找到了每组的起始标识,但卡在了如何“截止”到下一组出现的位置——这其实是正则里很常见的“区间匹配”场景,核心思路是用预查断言来定义匹配的终止条件,或者用非贪婪匹配结合边界限制。

先纠正下你原正则里的小问题:你的起始行正则(\w+\n\d+\.\d+\.\d+\s<.*>)里的\n应该是\s(空格),因为样例里的起始行是packagename 1.0.5 <url>,用\s能匹配任意空白符(空格、制表符都兼容)。

接下来给你两种实用的解决方案:

方法一:正向预查+DOTALL模式(推荐)

这个方法最直观,用正向预查(?=...)来告诉正则:“匹配到下一组起始行,或者文本结尾就停止”。同时开启DOTALL模式让.能匹配换行符(否则多行文本会被截断)。

最终正则:

(\w+\s+\d+\.\d+\.\d+\s+<.*?>)(.*?)(?=\w+\s+\d+\.\d+\.\d+\s+<.*?>|$)

拆解说明:

  1. (\w+\s+\d+\.\d+\.\d+\s+<.*?>):捕获每组的起始行(包名+版本+URL),用.*?非贪婪匹配URL避免过度延伸
  2. (.*?):非贪婪匹配中间的所有多行文本
  3. (?=\w+\s+\d+\.\d+\.\d+\s+<.*?>|$):正向预查,匹配的终止条件是“下一组起始行”或者“文本末尾”

代码示例(Python)

import re

# 你的样本文本
license_text = """packagename 1.0.5 <https://github.com/user/packagename>
此处为多行文本内容
可能还有第二行、第三行
packagename2 1.1.0 <https://github.com/user/packagename2>
此处为更多多行文本内容
甚至可能有空行

或者特殊格式的行"""

# 编译正则,开启DOTALL模式
pattern = re.compile(r'(\w+\s+\d+\.\d+\.\d+\s+<.*?>)(.*?)(?=\w+\s+\d+\.\d+\.\d+\s+<.*?>|$)', re.DOTALL)
matches = pattern.findall(license_text)

# 遍历输出每组结果
for idx, (pkg_info, content) in enumerate(matches, 1):
    print(f"=== 第{idx}组 ===")
    print(f"包信息:{pkg_info.strip()}")
    print(f"内容:\n{content.strip()}\n")

方法二:负向预查逐行匹配(无需DOTALL)

如果你的正则引擎不支持DOTALL,或者想更精准地逐行排除起始行,可以用负向预查(?!...)来跳过所有不是起始行的内容:

正则表达式:

(\w+\s+\d+\.\d+\.\d+\s+<.*?>)\n((?:(?!\w+\s+\d+\.\d+\.\d+\s+<.*?>).*\n?)*)

拆解说明:

  1. 第一部分还是捕获起始行
  2. (?:(?!起始行正则).*\n?)*:非捕获组,逐行匹配——只要当前行不是起始行,就匹配整行(包括换行符),直到遇到下一组起始行或结尾

注意事项

  • 如果包名包含连字符(比如my-package),把正则里的\w改成[\w-],避免漏匹配
  • 非贪婪匹配.*?是关键,去掉?会变成贪婪匹配,直接从第一组起始行匹配到文本末尾
  • 不同语言的正则引擎对DOTALL的开启方式不同:Python用re.DOTALL,Java用Pattern.DOTALL,JavaScript用/s修饰符

内容的提问来源于stack exchange,提问作者user3483203

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:15:28