0

My current regular expression only matches the nested pattern not the outermost @if....endif@ pattern. How can I modify my expression to match the outermost pattern. If the outermost pattern is removed from the string the expression should then match all before nested patterns. Many or the or-patterns are only relevant in the real world.

Regex:

(?<match>
@if\((?<statement>[^)]*)\){(?<ifblock>(?>
(?<open>@if\([^)]*\){)
    |<script[^>]+>.*?</script>
    |(?<valuetag>\@{(?<tag>[^}]+)})(?:(?:(\.|\$))(?<action>[^)@]+[)]))?
    |(?<configtag>@(?:(?<tagtype>cc|dc|sc|wc)){(?<tag>[^}\.]*)(?:(?:\.)(?<action>(?:ToLower|ToUpper|MaxLength)))?}(?:cc|dc|sc|wc)@)
    |(?<match>@weeknumber{(?<date>((?<valuetag>\@{(?<tag>[^}]+)})(?:(?:(\.|\$))(?<action>[^)@]+[)]))?|((0[1-9]|[12][0-9]|3[01])[-](0[1-9]|1[012])[-](19|20)\d\d)))}weeknumber@)
    |(?<tag>\@{(?<tagname>[^}]+)}[.]ReplaceText\((?<replace>[^;]+)[;]{1}(?<with>[^)]+)\))
    |(?<match>@(block|if)\((?<statement>[^)]*)\){(?<ifblock>.*)(?=)}end(block|if)@)
    |[^}@]+
    |@{value(\.[A-Z][0-9])?}
    |(?<-open>}endif@)
)*)
(?(open)(?!))
(
}else{(?<elseblock>(?>
(?<open>@if\([^)]*\){)
    |<script[^>]+>.*?</script>
    |(?<valuetag>\@{(?<tag>[^}]+)})(?:(?:(\.|\$))(?<action>[^)@]+[)]))?
    |(?<configtag>@(?:(?<tagtype>cc|dc|sc|wc)){(?<tag>[^}\.]*)(?:(?:\.)(?<action>(?:ToLower|ToUpper|MaxLength)))?}(?:cc|dc|sc|wc)@)
    |(?<match>@weeknumber{(?<date>((?<valuetag>\@{(?<tag>[^}]+)})(?:(?:(\.|\$))(?<action>[^)@]+[)]))?|((0[1-9]|[12][0-9]|3[01])[-](0[1-9]|1[012])[-](19|20)\d\d)))}weeknumber@)
    |(?<tag>\@{(?<tagname>[^}]+)}[.]ReplaceText\((?<replace>[^;]+)[;]{1}(?<with>[^)]+)\))
    |(?<match>@(block|if)\((?<statement>[^)]*)\){(?<ifblock>.*)(?=)}end(block|if)@)
    |[^}@]+
    |@{value(\.[A-Z][0-9])?}
    |(?<-open>}endif@)
)*)
(?(open)(?!))
)?
}endif@)

String:

        @if(base.SiteBID=='SOS'){
    <div class="floatleft reviewcontainer_outer" onclick="@if(base.IsSmartPhone=='False'){toogleReviewModalLightbox('@{house.id}', 0, 10);}endif@">
        @if(house.latestreview.amount<greaterthen>2){<div class="sos_sprite reviews@{house.category} sos_inline onlinecat_review_gfx@{house.latestreview.totalrankcss} floatleft reviewcontainer_sprite" title="@{house.latestreview.totalrank}"></div><p class="broedtekst floatleft link">@{house.latestreview.amount} @cc{txt_guestbook_result}cc@</p>}endif@
    </div>
                            @if(base.IsSmartPhone=='False'){toogleReviewModalLightbox('@{house.id}', 0, 10);}else{jhfr}endif@
    }endif@

I want the expression to match the whole string from @if to endif@

Magni Hansen
  • 82
  • 10
  • 1
    Regular expression are most often not the right tool to work with nested constructs. What are you trying to do? Wouldn't a parser be more appropriate? Which language / regex flavour are you using? Can you simplify your expression and sample first, leading to a [mcve]? – PJProudhon Feb 01 '19 at 10:15
  • The code is targeted for C#. I'm testing my regex with regex101.com, where I paste in the regex and string. Running the regex with these options: global, singleline, insensitive, ignore whitespace. Maybe a two-way parser is better suited, i'm trying to solve my issue with regex. – Magni Hansen Feb 01 '19 at 10:24
  • Sorry not regex101.com but http://regexhero.net/tester/ app. – Magni Hansen Feb 01 '19 at 10:35
  • @PJProudhon you are probably right. You can send answer. Regex is not the most suitable tool for the parser. I dropped regex in stead of another solution. First traversing the string and replacing each @if and endif@ with an incrementor i.e. @1if .. endif1@. Afterwards I used a non-greedy regex to collect the content. Example of my string after replacing with an incrementor. `@1if @2if @3if @4if ... endif4 endif3@ }2else{ @3if ... endif3@ endif2@ endif1@` – Magni Hansen Feb 04 '19 at 09:02
  • Is it Razor ? If so I'll give a try tonight. – PJProudhon Feb 04 '19 at 09:11
  • Almost, it's a Razor look-alike engine with some extra features. – Magni Hansen Feb 05 '19 at 10:30

1 Answers1

0

I tried with these and they worked:

(@if.+\\n+\\D+.*\\W+.*\\B.*\\n.*\\n.*\\n.*endif@)

This one below looks shorter.

(@if.+\\n+\\D+.*\\W+.*\\B.*\\n.*\\n.*\\n.*)

Both work. Tested on regex101.com

Laenka-Oss
  • 939
  • 2
  • 17
  • 25