如何在正则表达式中有未定义数量的捕获?

How to have an undefined amount of captures in a regex?

我正在制作一种简单的基于堆栈的语言,它使用 命令 来操作堆栈。当我在源代码中找到一个命令时,我使用这个正则表达式来分离出实际的命令名称,例如 sum,以及命令的参数。参数用三角括号括起来并用逗号分隔。

这是我目前使用的正则表达式:

(?<command>[^<>\s]+)(\<(?<args>(\d+)+(?>,\s*\d+)*)\>)?

现在可以正常工作了,这里有一些工作示例:

+              => command: '+', args: nil
sum<5>         => command: 'sum', args: '5'
print<1, 2, 3> => command: 'print', args: '1, 2, 3'

除最后一个外,这每一个都完全符合我的要求。我的问题是,有没有办法分别捕获每个参数?我的意思是这样的:

print<1, 2, 3> => command: 'print', args: ['1', '2', '3']

顺便说一下,我使用的是最新的 Ruby 正则表达式引擎。

无法使用简单的正则表达式在 Ruby 正则表达式中重复捕获组来获得这样的输出,因为引擎不保留捕获堆栈。

您需要将第二次捕获与 , 拆分为 post 处理步骤。

Ruby demo:

def cmd_split(s)
    rx = /(?<command>[^<>\s]+)(<(?<args>(\d+)+(?:,\s*\d+)*)>)?/
    res = []
    s.scan(rx) { 
        res << ($~[:args] != nil ? 
            Hash["command", $~[:command], "args", $~[:args].split(/,\s*/)] : 
            Hash[$~[:command], ""]) }
    return res
end

puts cmd_split("print<1, 2, 3>") # => {"command"=>"print", "args"=>["1", "2", "3"]}
puts cmd_split("disp<1>")        # => {"command"=>"disp", "args"=>["1"]}
puts cmd_split("+")              # => {"+"=>""}