问题在于包含嵌套括号的语言(或者实际上是嵌套的任何东西,IOW 任何需要递归的东西)都是不规则的,它们至少是上下文无关的。这意味着它们不能用常规语法来描述。正则表达式是正则文法的紧凑符号。因此,嵌套括号不能用正则表达式描述。
但是,我们在这里讨论的不是正则表达式,而是Regexps。虽然它们的语义和语法(非常)松散地基于正则表达式,但它们完全不同,尤其是更强大。根据您使用的 Regexp 的特定风格,它们可能会也可能不会表达递归并因此解析嵌套的括号。 Perl Regex,例如 can 解析嵌套括号。我不确定 Ruby 的 Regexp 是否可以,但我真的不在乎,因为 Regexp 比正则表达式更强大的方式通常是通过在它们上添加越来越多的语法来实现的。
这会将原本设计简单的正则表达式变成难以理解的怪物。 (如果你一眼就知道@Anon 发布的 Perl Regex 做了什么,那就去吧。但我不能,因此我不想使用它。)
我更喜欢使用更强大的解析器,而不是复杂的Regexp。
在这种情况下,你有一个上下文无关的语言,因此你可以使用一个非常简单的递归下降解析器。您可以通过使用正则表达式处理那些 正则的子部分来进一步简化递归下降解析器。最后,如果你将递归下降解析器中的递归替换为迭代 + 变异,并巧妙地利用 Ruby 的布尔语义,整个解析器基本上会浓缩为这一行:
while str.gsub!(/\([^()]*?\)/, ''); end
我觉得还不错。
这是整个过程,去掉了一些重复的空白,(当然)还有一个测试套件:
require 'test/unit'
class TestParenthesesRemoval < Test::Unit::TestCase
def test_that_it_removes_even_deeply_nested_parentheses
str = 'This is (was?) some ((heavily) parenthesized (but not overly so
(I hope))) text with (superflous) parentheses: )(.'
res = 'This is some text with parentheses: )(.'
while str.gsub!(/\([^()]*?\)/, ''); end
str.squeeze!(' ')
assert_equal res, str
end
end