2016-11-08 17 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("+")    # => {"+"=>""} 
相關問題