如何在lua中通过regexp重复匹配多个表达式

如何在lua中通过regexp重复匹配多个表达式,regex,lua,Regex,Lua,我正在学习lua。regexp中有一些问题。 我有一些字符串: text = "aaab1aaac-aac1d2b5hhpt456d5h9h8" 我希望得到如下结果: "b1", "c1b2b5", "t4", "d5h9h8" 我编写代码如下 local st,ed while true do st,ed = string.find(text,"([a-z][1-9])+",ed) --the regexp if st==nil then break

我正在学习lua。regexp中有一些问题。 我有一些字符串:

text = "aaab1aaac-aac1d2b5hhpt456d5h9h8"
我希望得到如下结果:

"b1", "c1b2b5", "t4", "d5h9h8"
我编写代码如下

local st,ed
while true do
    st,ed = string.find(text,"([a-z][1-9])+",ed)  --the regexp
    if st==nil then
        break
    else
        print(string.sub(text,st,ed))
    end
    ed=ed+1
end

但是它没有打印正确的结果

我不知道lua,但是这个正则表达式怎么样:

"((?:[a-z][1-9])+)"

正如@Yu Hao在一篇文章中已经提到的 , Lua模式与 “regex”我们大多数人都习惯了。 但这其实不是问题,因为Lua提供了优秀的 ,这是 由该语言的主要开发人员之一编写

您要求的模式可以用LPEG编写,如下所示:

local lpeg      = require "lpeg"
local lpegmatch = lpeg.match
local R, C      = lpeg.R, lpeg.C

local match_alpha_n_digit
do
  local alpha       = R "az" -- + R "AZ" -- for uppercase
  local digit       = R "09"
  local sequence    = C ((alpha * digit)^1) -- capture longest sequence of (alpha, digit) pairs
  local pattern     = (sequence + 1)^1
  match_alpha_n_digit = function (str)
    if not str or type (str) ~= "string" then return end
    return lpegmatch (pattern, str)
  end
end

text   = "aaab1aaac-aac1d2b5hhpt456d5h9h8"

print (match_alpha_n_digit (text))
--- or capture the result in a table:
some_table = { match_alpha_n_digit (text) }
这样,它被包装在一个函数中
match\u alpha\u n\u digit()
可以在表构造函数中调用的

也可以编写接收任意额外数据的模式 然后我们可以在匹配时使用参数检索的参数 捕获 (). 例如,此方法允许使用函数迭代所有匹配项:

local lpeg      = require "lpeg"
local lpegmatch = lpeg.match
local R, C      = lpeg.R, lpeg.C
local Cmt, Carg = lpeg.Cmt, lpeg.Carg

local iter_alpha_n_digit
do
  local alpha       = R "az"
  local digit       = R "09"
  local sequence    = Cmt (C((alpha * digit)^1) * Carg (1),
                           function (_, _, match, fun)
                             fun (match)
                             return true
                           end)
  local pattern     = (sequence + 1)^1

  iter_alpha_n_digit = function (str, fun)
    if not str or type (str) ~= "string"   then return end
    if not fun or type (fun) ~= "function" then return end
    return lpegmatch (pattern, str, nil, fun)
  end
end

text   = "aaab1aaac-aac1d2b5hhpt456d5h9h8"

iter_alpha_n_digit (text, print) -- iterate matches with the print() function
这里我们将内置的
print()
函数应用于匹配项,但是 它可以是任何其他函数。

尝试以下操作:


这里是使用LPEG的替代方案,在这种情况下,使用简单的循环是有效的:

function findzigs(text)
    local items = {}
    local zigzag = nil
    local prevI1=-2
    local i1,i2 = text:find("%a%d") 
    while i1~=nil do
        local pair = text:sub(i1,i2)
        if i1-2 == prevI1 then
             zigzag = zigzag .. pair
        else
             if zigzag then table.insert(items, zigzag) end
             zigzag = pair
        end
        prevI1 = i1
        i1,i2 = text:find("%a%d", i2+1) 
    end
    if zigzag then table.insert(items, zigzag) end
    return items
end

可能会被清理以删除重复的“if-zigzag”和“text:find”,但你明白了。它会给出你所需要的结果

OP代码的真正问题在于Lua模式匹配与regex不同。这在正则表达式中有效,但在Lua模式中无效(除非有正则表达式库的支持)。不要这样做。我发现Lua不支持在“()”之后插入“+”。“([a-z][1-9])+”的表达式不能处理任何内容。另一种方式:
对于文本中的s:gsub(“%l%d”,“\0%0\0”):gsub(“%z%z”,”):gmatch“%z(.-)%z”不打印结束
回答得好。看起来是个更好的方法。谢谢。这很聪明,但需要太多的技巧来满足我的口味。我添加了一个基于简单循环的解决方案,其中包含文本:find(),更多行,但逻辑更清晰(IMO)。
function findzigs(text)
    local items = {}
    local zigzag = nil
    local prevI1=-2
    local i1,i2 = text:find("%a%d") 
    while i1~=nil do
        local pair = text:sub(i1,i2)
        if i1-2 == prevI1 then
             zigzag = zigzag .. pair
        else
             if zigzag then table.insert(items, zigzag) end
             zigzag = pair
        end
        prevI1 = i1
        i1,i2 = text:find("%a%d", i2+1) 
    end
    if zigzag then table.insert(items, zigzag) end
    return items
end