如何在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
    else
        print(string.sub(text,st,ed))
    end
    ed=ed+1
end

但它并没有输出正确的结果。

点赞
用户372239
用户372239

我不知道 Lua,不过这个正则表达式怎么样:

"((?:[a-z][1-9])+)"
2014-01-19 11:22:22
用户441830
用户441830

正如@Yu Hao在评论中提到的那样,Lua模式与我们大多数人使用的“正则表达式”不同且有些不那么强大。但这实际上并不是问题,因为Lua提供了由语言的主要开发者之一编写的优秀的LPEG库

你正在请求的模式可以在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_alpha_n_digit()函数中,您可以在表构造器内调用该函数。

还可以编写接收任意额外参数的模式,然后在匹配时使用参数捕获(lpeg.Carg())检索这些参数。该方法允许例如使用函数迭代所有匹配:

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()函数应用于匹配,但其实是可以替换为任何其他函数的。

2014-01-19 12:46:30
用户107090
用户107090

尝试这个行业技巧

text = "aaab1aaac-aac1d2b5hhpt456d5h9h8"
aux = text:gsub("%l%d","\1\1")

for b,e in aux:gmatch("()\1+()") do
    print(text:sub(b,e-1))
end
2014-01-19 14:13:52
用户869951
用户869951

以下是另一种方法,使用一个简单的循环在这种情况下可以工作:

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”,但您已经了解了这个想法。它恰好提供您需要的结果。

2014-01-20 03:19:00