Lua中平衡括号的可选捕获

4

假设我有以下格式的行:

int[4] height
char c
char[50] userName 
char[50+foo("bar")] userSchool 

如您所见,括号内的表达式是可选的。

我能否使用Lua的string.match()解析这些字符串?

下面的模式适用于包含括号的行:

line = "int[4] height"
print(line:match('^(%w+)(%b[])%s+(%w+)$'))

但是,有没有一种模式可以处理可选的括号呢?以下内容无法正常工作:

line = "char c"
print(line:match('^(%w+)(%b[]?)%s+(%w+)$'))

这个模式可以用另一种方式来解决吗?

2个回答

4
与正则表达式不同,Lua模式中的?匹配一个单一字符。
您可以使用or运算符来完成此任务,如下所示:
line:match('^(%w+)(%b[])%s+(%w+)$') or line:match('^(%w+)%s+(%w+)$')

一个小问题是,Lua只会保留表达式中的第一个结果。根据您的需求,可以使用if语句或者像这样给整个字符串添加第一个捕获

print(line:match('^((%w+)(%b[])%s+(%w+))$') or line:match('^((%w+)%s+(%w+))$'))

谢谢。我知道这种方法,即调用match()两次。问题是我实际上需要修改字符串(使用gsub()而不是match();为了简单起见,我在问题中省略了它),我不希望第二次调用gsub()看到第一次所做的更改。 - Niccolo M.
@NiccoloM。为什么不提出一个新问题,询问如何使用string.gsub来解决你的原始问题呢? - Yu Hao

3

LPeg 可能更适合您的情况,特别是如果您计划扩展语法。

local re = require're'

local p = re.compile( [[
    prog <- stmt* -> set
    stmt <- S { type } S { name }
    type <- name bexp ?
    bexp <- '[' ([^][] / bexp)* ']'
    name <- %w+
    S    <- %s*
]], {set = function(...)
    local t, args = {}, {...}
    for i=1, #args, 2 do t[args[i+1]] = args[i] end
    return t
end})

local s = [[
int[4] height
char c
char[50] userName
char[50+foo("bar")] userSchool
]]

for k, v in pairs(p:match(s)) do print(k .. ' = ' .. v) end

--[[
c = char
userSchool = char[50+foo("bar")]
height = int[4]
userName = char[50]
--]]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接