LUA 错误 "pattern too complex" - 桌面模拟器

LUA error "pattern too complex" - Tabletop Simulator

我有一个字符串,我正在尝试使用 LUA 模式匹配从中提取特定部分。我将其保存为正则表达式,您可以看到 here,以及提取我想要的确切部分(绿色捕获组)的字符串和正则表达式语法。我已将其转换为 LUA 等效模式语法,即:

result = {string.match(description, "Weapons.-\n(.*)\n\n")}

但它错误地说“模式太复杂”。奇怪的是,我试图解决这个问题,因为我假设我在转换中犯了一个错误,如果我删除最后一个 \n 它确实有效,但它也捕获了能力部分,这是不可取的。我 认为 我的语法是正确的,因为当我删除 \n 并将其从正则表达式中删除时,它们都匹配相同的数据......所以当我在LUA中添加两个\n??

我有很多不同的方法,但我得到了一些奇怪的结果,所以我开始认为这是 LUA 本身的一种错误。

我想指出的一件可能有帮助的额外事情是,我正在桌面模拟器中执行此操作,我相信它使用 Moonsharp(它是一个 LUA 解释器)。任何人都可以建议这里发生了什么或如何调整它以捕获我想要的数据吗?

谢谢,

您可以使用

result = s:match("Weapons.-\n(.-)\n\n")

参见online Lua demo详情:

  • Weapons - 一句话
  • .- - 任意零个或多个字符,尽可能少
  • \n - 换行符
  • (.-) - 第 1 组:任意零个或多个字符,尽可能少
  • \n\n - 两个换行符。

I have lots of differnt ways and I get some weird results so I am starting to think that this is kind of bug in LUA itself.

这似乎是底层 MoonSharp implementation 的错误。正如已经在评论中指出的那样,您的模式在使用官方 PUC Lua 5.3 实现的大型输入字符串上运行得很好:

> description = "[-]Weapons" .. ("."):rep(1e6) .. "\n" .. ("."):rep(1234567) .. "\n\n[-]More Stuff" .. ("."):rep(1e7)
> #string.match(description, "Weapons.-\n(.*)\n\n")
1234567

考虑到 MoonSharp 的不可靠模式实现(代码似乎移植了 Lua 实现,但我认为他们忘记在函数返回时再次递增 matchdepth),我' d 通过循环遍历行或使用 find 查找模式项(尽管不使用模式)来实现这种不带模式的匹配。

下面的函数正是针对固定模式 "Weapons.-\n(.-)\n\n" 执行此操作的。注意如何将所有 find 调用的最后一个参数设置为 true 以防止模式匹配:

local function extract_weapons(description)
    local _, end_weapons = description:find("Weapons", 1, true)
    if not end_weapons then return end
    local _, end_newline = description:find("\n", end_weapons + 1, true)
    if not end_newline then return end
    local start_newlines = description:find("\n\n", end_newline + 1, true)
    if not start_newlines then return end
    return description:sub(end_newline + 1, start_newlines - 1)
end

因此,对于可能遇到此问题的任何其他人,这里是解决方法及其发生的原因。

正如其他人所说,这确实是由于桌面模拟器 LUA 解释器中的一个错误。 TTS 不使用原生 LUA,而是使用名为 MoonSharp v2.0 的解释器。这个版本有这个错误,它 似乎 当你的正则表达式(模式)匹配一个长字符串时它会出错。只想强调最后一句话 - 不是你正在解析的字符串有这个限制,而是从匹配返回的字符串,原始字符串可以是任意长度(据我所知)。

解决方法是加入变通办法。我首先将较大的字符串(请参阅上面的字符串示例的正则表达式 link)分成单独的行,并用它们创建一个数组(table in LUA speak)。然后,我通过遍历数组中的每个项目并将它们连接起来,重建了原始字符串。在循环中,我有一个 if 语句来查找字符串“Abilities”,一旦匹配,它将退出循环。这就是我基本上有一个与原始字符串相同但减去了能力部分的方式。也许这个变通办法可以帮助遇到此问题的其他人。

代码片段在这里,您可以看到它的要点:

--this first line gets the data you see in the regex I listed above
local weaponSection = {string.match(description, "Weapons.-\n(.*)\n")}
-- Because Moonsharp regex is bugged we have to split the entire weapon section string  into subcomponents then rebuild it
    local temptable = {}
    local rebuiltWeaponSection = ""
    -- split the larger string into line by line, then insert into array - this bring "abilities" section across which we don't want and can't exclude due to bug explained above
        for weapon in string.gmatch(weaponSection[1], ".-\n") do
            table.insert(temptable, weapon)
        end
        -- now loop through the array and concat each line to a new string
        for _, weapon in ipairs(temptable) do
            -- this if statement looks for the abilities line and then exits loop when he sees it. this ultimately ends up rebuilding it all without the abilities section
            if string.match(weapon, "Abilities") then
                break
            else
                rebuiltWeaponSection = rebuiltWeaponSection .. weapon
            end
        end