我需要一个正则表达式,它可以在字符串中找到任何可能包含匹配括号的不匹配括号(打开或关闭)。
这里存在stackoverflow的问题,但我还没有找到一个有效的基于正则表达式的解决方案。
我提出了一个正则表达式,使用负向前瞻找到了无与伦比的开括号\((?![^)]+\))
,但我似乎无法找出无与伦比的结束括号所需的对立面。
编辑:找到无法匹配的开括号的上述正则表达式无法正常工作。例如。它将错过多个开括号后跟一个右括号的情况(另见注释)
这是我在Rubular上尝试过的测试字符串:
one) ((two) (three) four) (five)))
请注意,字符串可以包含任何类型的字符,包括引号,短划线等。
答案 0 :(得分:10)
简短的回答是你找不到带有正则表达式的不匹配的括号。正则表达式编码regular languages,而所有正确匹配括号的语言为context-free language。
答案 1 :(得分:4)
这是一种基于正则表达式的解决方案:)
def balanced?( str, open='(', close=')' )
re = Regexp.new( "[\\#{open}\\#{close}]" )
str.scan(re).inject(0) do |lv,c|
break :overclosed if lv < 0
lv + (c==open ? 1 : -1)
end == 0
end
s1 = "one) ((two) (three) four) (five)))"
s2 = "((one) ((two) (three) four) (five))"
s3 = "((one) ((two) (three) four) (five)"
puts balanced?(s1), #=> false
balanced?(s2), #=> true
balanced?(s3) #=> false
答案 2 :(得分:1)
Ruby的Oniguruma库可以解析LALR(n)语法,包括HTML。引用README:
r = Regexp.compile(<<'__REGEXP__'.strip, Regexp::EXTENDED)
(?<element> \g<stag> \g<content>* \g<etag> ){0}
(?<stag> < \g<name> \s* > ){0}
(?<name> [a-zA-Z_:]+ ){0}
(?<content> [^<&]+ (\g<element> | [^<&]+)* ){0}
(?<etag> </ \k<name+1> >){0}
\g<element>
__REGEXP__
p r.match('<foo>f<bar>bbb</bar>f</foo>').captures
上面的代码当然比真正的HTML解析器简单得多,但它匹配嵌套标记。另外,你应该注意到制作一个非常慢的正则表达式非常简单(在几分钟的范围内解析80个符号的字符串)。
最好使用Treetop等真正的解析器来完成此任务。