2012-02-15 20 views
3

マッチするかっこを含む可能性のある文字列の中で、不一致の中かっこ(開始または終了)を見つける正規表現が必要です。マッチしない括弧を見つけるための正規表現

ここには、stackoverflowに関する質問がありますが、動作する正規表現ベースのソリューションが見つかりませんでした。

私は、否定的な先読みを使用して、一致しない開いた中括弧\((?![^)]+\))を見つけましたが、一致しない閉じ括弧に必要な反対のものを見つけることはできません。

EDIT:意図したとおりに比類のないオープンな括弧を見つけるために上記の正規表現は動作しません。例えば。それはここでは、複数のオープン中括弧は、単一の閉じ括弧が続いている例(コメントも参照)

を欠場する私はRubular上で実験してきたというのが私のテスト文字列です:

one) ((two) (three) four) (five))) 

に留意されたいです。文字列には、引用符、ダッシュなどの任意のタイプの文字を含めることができます。

+4

これは、一般的なケースで動作する正規表現ベースのソリューションがないためです。これは、あなたが[regexでXMLを解析できない](http://stackoverflow.com/a/1732454/13)(これは一般的な場合)と同じ理由です。 –

+1

本当に正規表現でなければなりませんか?なぜ単純なループではない 'string.each_char {| c | ...} '? –

+2

厳密なregexp言語はできません..しかし、PCREのような一般的な拡張正規表現は可能です。 http://stackoverflow.com/questions/562606/regex-for-checking-if-a-string-has-mismatched-parentheses – Kaganar

答えて

8

簡単な答えは、正規表現で一致しないカッコを見つけることができないということです。正規表現はregular languagesをエンコードしますが、適切に一致するすべての括弧の言語はcontext-free languageです。

4

はここLALR HTMLを含む(n)の文法を、解析することができますソート-の正規表現ベースのソリューション:)

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 
+0

ニース、ありがとう:) –

1

Rubyの鬼車ライブラリです。 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のような実際のパーサーを使用する方がよいでしょう。

関連する問題