2016-11-08 38 views
1

我正在制作一个简单的基于堆栈的语言,它使用命令来操作堆栈。当我在源代码中找到一个命令时,我使用这个正则表达式来分隔出实际的命令名,例如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正则表达式引擎。

+1

没有,使用简单的regex反复捕获组不会这样的。你需要用'''分割第二个捕获,作为后处理步骤。 Ruby正则表达式引擎不保留捕获堆栈。 –

+0

这太遗憾了 - 谢谢,无论如何 – Zac

+1

很少有正则表达式支持捕获组堆栈,只有.NET和Python PyPi正则表达式模块默认支持它们。一个接近的模式将是['/(?:\ G(?!\ A),\ s * |(? [^ <> \ s] +)<)(? \ d +)/'](http:// rubular。 com/r/BDocFayOkZ),但它使用多个匹配项,并且如果输入中有多个匹配项,则可能无法分隔它们。 –

回答

1

因为引擎不保留捕获堆栈,所以使用一个简单的正则表达式来重复捕获Ruby正则表达式组是不可能的。

您需要将第二次捕获与,分开作为后处理步骤。

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("+")    # => {"+"=>""}