2015-05-26 55 views
2

我目前正在研究一个ruby程序来计算术语。除了一件事情之外,它工作得很好:括号。我需要过滤内容或至少将内容放入数组中,但我已尝试了一个小时以提出解决方案。这里是我的代码:分割括号内容而不分开括号ruby

splitted = term.split(/\(+|\)+/) 

我需要一个数组,而不是括号,例如:

"1-(2+3)" #=>["1", "-", ["2", "+", "3"]] 

我已经尝试过这样的:

/(\((?<=.*)\))/ 

但它返回:

Invalid pattern in look-behind. 

有人可以帮我t他?

UPDATE

我忘了提,我的程序会分裂术语,我只需要括号的内容是一个数组。

+0

我觉得stringscanner更适合这类任务。 –

+0

无效的消息似乎是因为在大多数引擎中(除了Dot-Net),lookbehinds不能具有可变长度。另一件事是,如果你试图独立解析'(2 + 3)',除非Ruby支持递归,否则你不能这么做。而且,我不知道它是否。另一种方法是自己解析它,逐个字符地跟踪堆栈的嵌套。 – sln

+0

这将是一个适当的嵌套示例:'(5-(3 * 2(4 + 1)-9)+7)* 4' – sln

回答

0

如果您需要跟踪数组括号的层次结构,您将不会仅仅使用正则表达式来管理它。您需要逐字解析字符串,并保留一堆表达式。

伪代码:

  • 表达式=新的堆栈
  • 上堆添加新的数组
  • 而字在字符串:
    • 如果单词是 “(”:添加新的阵列上层叠
    • 否则如果单词是“)”:从堆栈中删除最后一个数组并将其添加到堆栈的(下一个)最后一个数组
    • 否则:单词添加到堆栈
  • 当退出循环的最后一个数组,应该只有一个堆叠阵列(如果没有,你有不一致的开/关括号)。

注意:如果您的最终目标是评估表达式,您可以节省时间并在Postfix中解析字符串(又名Reverse-Polish Notation)。 另请考虑使用off-the-shelf libraries

0

解决方案取决于您期望的括号之间的模式,您尚未指定。 (例如,对于"(st12uv)",您可能需要["st", "12", "uv"],["st12", "uv"],["st1", "2uv"]等)。如果,在你的榜样,它是一个自然数后跟一个+,紧接着又自然数,你可以这样做:

str = "1-(2+ 3)" 

r =/
    \(\s* # match a left parenthesis followed by >= 0 whitespace chars 
    (\d+) # match one or more digits in a capture group 
    \s* # match >= 0 whitespace chars 
    (\+) # match a plus sign in a capture group 
    \s* # match >= 0 whitespace chars 
    (\d+) # match one or more digits in a capture group 
    \s* # match >= 0 whitespace chars 
    \)  # match a right parenthesis 
    /x 

str.scan(r0).first 
    => ["2", "+", "3"] 

假设,而不是+可能是+-*/。然后,你可以更改:

(\+) 

到:

([-+*\/]) 

需要注意的是,在一个字符类,+不需要进行转义,如果它是第一个或最后一个字符-不需要进行转义(在这种情况下,它不代表范围)。

顺便提一下,您收到错误消息“无效的后向模式”,因为Ruby的周期不能包含可变长度匹配(即.*)。通过使用\K来代替积极向后看,你可以解决这个问题。例如,

r =/
    \d+ # match one or more digits 
    \K # forget everything previously matched 
    [a-z]+ # match one or more lowercase letters 
    /x 

"123abc"[r] #=> "abc" 
相关问题