2010-04-15 38 views
6

那么为什么这不起作用?我正在创建一个匹配公式的正则表达式(这是一个更大的标准描述的一部分)。但是我被困在这里,因为它似乎不想匹配公式中的嵌入式公式。ruby​​递归正则表达式

stat  = /(Stat3|Stat2|Stat1)/ 

number_sym = /[0-9]*/ 
formula_sym = /((target's)?#{stat}|#{number_sym}|N#{number_sym})\%?/ 
math_sym = /(\+|\-|\*|\/|\%)/ 

formula  = /^\((#{formula}|#{formula_sym})(#{math_sym} (#{formula}|#{formula_sym}))?\)$/ 

p "(target's Stat2 * N1%)".match(formula).to_s #matches 
p "((target's Stat2 * N1%) + 3)".match(formula).to_s #no match 
p "(Stat1 + ((target's Stat2 * N1%) + 3))".match(formula).to_s #no match 

回答

7

当您使用#{ }语法,红宝石RegExp对象转换为使用to_s的字符串。你看,当您转换RegExp对象的字符串会发生什么:

irb> re = /blah/ 
    => /blah/ 
irb> re.to_s 
    => "(?-mix:blah)" 
irb> "my regex: #{re}" 
    => "my regex: (?-mix:blah)" 
irb> /my regex: #{re}/ 
    => /my regex: (?-mix:blah)/ 

为了得到你想要的字符串(在我的例子,“嗒嗒”),使用Regexp#source方法:

irb> re.source 
"blah" 

所以要用你的例子:在你的formula定义#{formula} s的转换为空字符串:

formula_sym = /((target's)?#{stat.source}|#{number_sym.source}|N#{number_sym.source})\%?/ 
+0

谢谢......我确实发现它为什么不能正常工作......我猜应该把我的问题解释为“我怎样才能得到它”......看起来像#{formula.source}显示公式仍然是零。 – 2010-04-15 18:53:19

1

不能使用递归这样。你想要的不是正则表达式的能力 - 正则表达式甚至不能匹配嵌套的括号。我怀疑你需要一个真正的解析器来做你想做的事情。例如,请查看treetop

+0

优秀... treetop将允许我轻松地将我当前的定义规范迁移到它。谢谢! – 2010-04-15 19:12:46

3
/(
    (?<non_grouping_char> 
    [^\(\{\[\<\)\}\]\>] 
){0} 
    (?<parens_group> 
    \(\g<content> \) 
){0} 
    (?<brackets_group> 
    \[ \g<content> \] 
){0} 
    (?<chevrons_group> 
    \< \g<content> \> 
){0} 
    (?<braces_group> 
    \{ \g<content> \} 
){0} 
    (?<balanced_group> 
    (?> 
     \g<parens_group> | 
     \g<brackets_group> | 
     \g<chevrons_group> | 
     \g<braces_group> 
    ) 
){0} 
    (?<content> 
    (?> \g<balanced_group> | \g<non_grouping_char>)* 
){0} 
    \A \g<content> \Z 
)/uix 

啤酒我,如果这可以帮助你。适用于我。适用于允许命名组的任何正则表达式引擎。它将验证任何没有组或嵌套字符组的任何内容到任何深度。

+1

如果我们见面,我肯定会给你一杯啤酒。你最喜欢什么味道? :)从那时起,我投票了! – Stephan 2012-10-11 08:42:52