Abbondanza が述べたように、これを正規表現で行う場合は、グループのバランスを取る必要があります。警告する必要がありますが、これは良い解決策にはなりません。.NET の正規表現エンジンは、このようなケースを処理できる数少ないエンジンの 1 つですが、実際には推奨される方法ではありません。おそらく、言語を手動で解析したほうがよいでしょう。これにより、ネスト レベルをはるかに簡単に数えることができます。
とにかく、生産的なソフトウェアでこのタスクに正規表現が不適切である理由を示すために、ここに正規表現 (RegexOptions.IgnorePatternWhitespace
と を使用RegexOptions.Singleline
) を示します。
(?<=\[!--@Else--\]) # Make sure that our match begins right after an else
# block.
[^\[]* # Match as many non-[ characters as possible (the actual
# statement)
(?= # This lookahead will assert that the previous statement
# was a top-level Else
(?<Depth>) # Push one capture onto the stack "Depth" (because, if
# this is one of the desired "Else"s we are exactly one
# level deep
(?> # Start a subpattern for anything that could follow and
# suppress backtracking (because the alternatives are
# mutually exclusive)
(?<Depth>\[!--@If\([^()]*\)--\])
# If we encounter an If block, push a new capture onto
# the stack (because the nesting level rises)
| # OR
(?<-Depth>)\[!--@EndIf--\]
# IF we can pop a capture from the stack, consume an
# EndIf. If we cannot, the named group will fail. Hence
# we can only consume one EndIf more than we already
# encountered Ifs.
| # OR
(?!\[!--@EndIf--\]). # If this character does not mark the beginning of an
# EndIf, consume an arbitrary character.
)* # Repeat as long as possible.
$ # Make sure we have reached the end of the string.
(?(Depth)(?!)) # If there is anything left on the stack, fail, too,
# because there are some Ifs that were not closed, so
# the syntax was invalid anyway.
# You can leave this out if you have convinced yourself
# beforehand that the overall nesting syntax is correct.
) # End of lookahead.
今、これはすでにかなりの獣であり、この小説のコメントなしではほとんど誰も理解できないでしょう.
しかし、仮定を単純化することに言及しました。どうぞ。
If
条件内に括弧を使用することはできません。それを行いたい場合は、それらの正しいネスティングも確認する必要があります。ここで行ったことよりも少し単純ですが、それでも括弧のスタックを上下に構築する必要があります。
- 主な問題はおそらく実際の試合
[\[]]*
です。開き括弧は一切使用できないため、Else
ブロック内に条件ステートメントを含めることはできません。これを許可したい場合は、ほとんどすべてを実際の一致に再度コピーする必要があります。これにより、どのIf
s とEndIf
s が の中にありElse
、どの s がその後に来るかがわかります。
ご覧のとおり、すべてのケースを 100% カバーする正規表現ソリューションを取得するには、そのコードを完全に保守不可能にする必要があります。そのため、文字列を手動で分析し、ある種の構文ツリーを構築することを検討する必要があります。Else
このようにして、見つけたい特定の s を簡単にトラバースできるネスト構造の OOP 表現を取得します。