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

如何用Lua模式匹配正确解析带嵌套的MediaWiki参数语法?

解决MediaWiki参数转Lua的模式匹配问题

Lua的模式匹配本身不支持递归匹配,没法用单一正则/模式处理带嵌套大括号的MediaWiki参数语法。要解决你遇到的三个问题,得用层级计数+循环遍历的方式处理,具体思路如下:

1. 准确定位完整的{{{...}}}块

核心是跟踪大括号的层级,找到每个参数块的完整范围:

  • 遍历字符串,先定位所有{{{的起始位置
  • 从起始位置后开始计数:每遇到{层级+1,遇到}层级-1
  • 当层级回到0时,说明找到了对应的闭合}}},此时提取整个参数块

示例Lua代码:

function extractParamBlocks(text)
    local blocks = {}
    local idx = 1
    local len = #text

    while idx <= len do
        -- 找到下一个{{{的起始位置
        local start = text:find("{{{", idx)
        if not start then break end

        local level = 3 -- 初始三个左大括号,层级为3
        local current = start + 3

        -- 遍历找闭合的}}}
        while current <= len do
            local char = text:sub(current, current)
            if char == "{" then
                level = level + 1
            elseif char == "}" then
                level = level - 1
                -- 层级归0,说明找到完整闭合
                if level == 0 then
                    local block = text:sub(start, current)
                    table.insert(blocks, block)
                    idx = current + 1
                    break
                end
            end
            current = current + 1
        end

        -- 若未找到闭合,跳过当前{{{继续查找
        if not current then idx = start + 3 end
    end

    return blocks
end

2. 拆分参数名与带嵌套的默认值

提取到完整参数块后,需要拆分参数名和默认值,同样要通过层级计数判断顶层的|分隔符(避免误拆分嵌套内容里的|):

  • 先去掉参数块外层的{{{和}}},得到内部内容
  • 遍历内部内容,跟踪层级,只在层级为0时识别分隔符|
  • 分隔后分别提取参数名和默认值

示例Lua代码:

function splitParamParts(block)
    -- 去掉外层的{{{和}}}
    local content = block:sub(4, #block - 3)
    local paramName, defaultValue
    local level = 0
    local splitPos = nil

    for i = 1, #content do
        local char = content:sub(i, i)
        if char == "{" then
            level = level + 1
        elseif char == "}" then
            level = level - 1
        elseif char == "|" and level == 0 then
            splitPos = i
            break
        end
    end

    if splitPos then
        paramName = content:sub(1, splitPos - 1):gsub("^%s+", ""):gsub("%s+$", "") -- 去首尾空格
        defaultValue = content:sub(splitPos + 1):gsub("^%s+", ""):gsub("%s+$", "")
    else
        paramName = content:gsub("^%s+", ""):gsub("%s+$", "")
        defaultValue = nil
    end

    return paramName, defaultValue
end

3. 递归转换为Lua兼容语法

对于默认值里嵌套的MediaWiki参数,需要递归处理,最终转换为Lua的短路求值语法(比如args.param or (args.alias or "default")):

function convertToLuaSyntax(block, argsName)
    argsName = argsName or "args" -- 默认用args作为参数表名
    local paramName, defaultValue = splitParamParts(block)

    if not defaultValue then
        return string.format("%s.%s", argsName, paramName)
    end

    -- 检查默认值是否也是MediaWiki参数块
    if defaultValue:find("^{{{") then
        local nestedLua = convertToLuaSyntax("{{{" .. defaultValue .. "}}}", argsName)
        return string.format("%s.%s or (%s)", argsName, paramName, nestedLua)
    else
        -- 默认值是普通字符串,转义引号
        local escapedDefault = defaultValue:gsub('"', '\\"')
        return string.format('%s.%s or "%s"', argsName, paramName, escapedDefault)
    end
end

对应解决你的三个具体问题

  • 问题1(嵌套匹配不完整):通过层级计数准确找到每个参数块的闭合位置,不会在嵌套中途截断
  • 问题2(移除大括号限制后匹配异常):只识别顶层的|分隔符,不会误拆分嵌套内容里的分隔符
  • 问题3(多参数匹配溢出):每个参数块的起始和闭合位置独立计算,不会跨块匹配相邻的参数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 14:42:49