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

如何将指定正则转换为LPEG分割模式?适配SemVer约束

正则转LPEG分割模式的问题与解决

问题描述

我需要将正则模式{ *(?<!-)[, ](?!-) *}转换为LPEG模式,用作分割规则——可以把2.5 2.6/2.5, 2.6分割成2.5和2.6,但遇到-时不执行分割,这是SemVer版本约束识别的一部分。我用了LPEG文档里的split函数:

local function split (str, sep)
   sep = l.P(sep)
   local elem = l.C((1 - sep)^0)
   local p = l.Ct(elem * (sep * elem)^0)   -- make a table capture
   return p:match(str)
 end

我的初步实现能处理带逗号的情况:

local h, sp = l.P'-', l.P' '
patt = sp^0 * (-h * l.S' ,' - h) * sp^0
split('2.5, 2.6', patt) -- 有效
split('2.5 2.6', patt) -- 失败,因首个sp^0匹配所有内容

但仅含空格的场景会失败,其他尝试还出现了无限循环。请问如何在保留原正则约束的同时解决该问题?


问题分析与修复

核心问题在于原分割模式的逻辑缺陷:sp^0会优先匹配所有空格,导致纯空格分隔的场景下,分隔符的核心匹配逻辑根本没机会触发。另外,原模式的否定逻辑可以更精准地对应正则的(?<!-)和(?!-)(负前后瞻)。

正确的LPEG分割模式实现

我们需要把分隔符逻辑调整为:前后不能是-的逗号或空格,同时前后可以有任意数量的空格,但必须确保核心分隔符(逗号/空格)存在。

修改后的完整代码如下:

local l = require'lpeg'

local function split(str, sep)
    sep = l.P(sep)
    local elem = l.C((1 - sep)^0)
    local p = l.Ct(elem * (sep * elem)^0)
    return p:match(str)
end

-- 构建符合要求的分隔符模式
local dash = l.P'-'
-- 核心分隔符:逗号或空格,且前后都不是减号,对应正则的(?<!-)[, ](?!-)
local sep_core = (-dash) * l.S', ' * (-dash)
-- 完整分隔符:核心分隔符前后可带任意空格,同时处理连续空格场景避免无限循环
local patt = l.P{
    l.P' '^0 * sep_core * l.P' '^0 +
    -- 匹配连续空格后递归,确保最终能定位到有效核心分隔符
    l.P' '^1 * l.V(1)
}

-- 测试用例验证
print(unpack(split('2.5, 2.6', patt))) -- 输出:2.5 2.6
print(unpack(split('2.5 2.6', patt))) -- 输出:2.5 2.6
print(unpack(split('2.5-2.6', patt))) -- 输出:2.5-2.6(不分割)
print(unpack(split('2.5 , 2.6', patt))) -- 输出:2.5 2.6
print(unpack(split('2.5  -  2.6', patt))) -- 输出:2.5  -  2.6(不分割)

关键说明

  1. sep_core:用LPEG的(-dash)实现正则的负前后瞻效果,确保分隔符的前后都不是减号。
  2. 递归分隔符模式:通过递归规则处理连续空格的场景,同时用l.P' '^1确保每次递归都至少匹配一个空格,避免无限循环。
  3. 空格匹配逻辑:将空格匹配放在核心分隔符的前后,既保留了原正则允许分隔符前后带任意空格的规则,又避免了纯空格吞掉所有内容的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 10:48:19