get inner patterns recursively using regex c#
Asked Answered
G

1

7

i know there are several questions about regex recursion in .net. I can write somewhat complex regex expressions but this recursion is beyond me, i am just not able to write it.

This are the questions closest to what i want.

first question, second question.

but it matches the entire string, i want the matches in a collection preferably the innermost match first or in some order. Also it matches on one opening character and one closing character. Mine is 2 chars for opening and closing, [! and !]

my input string will be something like this.

[!a='test' b='[!a='innertest' b='innervalue'!]'!]

I need to find the innertest section, [!a='innertest' b='innervalue'!], first and then evaluate it through one of my expression trees. then evaluate the parent one containing it.

Can anyone help with this?

Gambia answered 21/3, 2012 at 22:23 Comment(0)
B
13

Here's a pattern that might satisfy your needs:

^\[!((?<n>\w+='\[!)|(?<inner-n>!]')|\w+='(?!\[!)[^']*'| )*!](?!(n))$

It will give the innermost item for each item in order. To explain what I mean, given the code:

[!a='test' c='[!x='blah'!]' b='[!a='[!y='innermost'!]' b='innervalue'!]' !]

It will give the following matches (in the capture collection for the group "inner"):

x='blag'
y='innermost'
a='[!y='innermost'!]' b='innervalue'

So, for each x=y item in the [! .. !], it will give the matches in order from innermost outwards.

If you also want the overall expression to be captured you can modify it like this:

^(?<n>\[!)((?<n>\w+='\[!)|(?<inner-n>!]')|\w+='(?!\[!)[^']*'| )*(?<inner-n>!])(?!(n))$

Giving:

x='blag'
y='innermost'
a='[!y='innermost'!]' b='innervalue'
a='test' c='[!x='blag'!]' b='[!a='[!y='innermost'!]' b='innervalue'!]' 

And to explain the regex:

^       # start of string
\[!     # start of overall [! .. !]
(       # either ...
    (?<n>\w+='\[!)|     # a complex x='[! .. !]' containing a nested [! .. !] - push this onto the stack 'n'
    (?<inner-n>!]')|    # end of a nested [! .. !] - pop stack 'n', and capture the contents into 'inner'
    \w+='(?!\[!)[^']*'| # a simple x='asdf' with no nested [! .. !]
     )                  # or a space
*       # as many times as you want
!]      # the end of the overall [! .. !]
(?!(n)) # assert that the 'n' stack is empty, no mismatched [! .. !]
$       # end of string
Bazemore answered 21/3, 2012 at 22:45 Comment(4)
this looks good..Thank you for your help. i'm going to try it out. is there a way to tell the order, like innermost first, since I need to evaluate that first.Gambia
Not directly. You could work it out by using the Capture.Start and Capture.Length properties for each capture, since that will let you know which captures contain which other captures. However, if each x='...' can only depend on what it contains, then this order should work fine.Bazemore
it is very close to what i want. thank you for your effort. You must be a genius!!! One final question on this. If I wanted to change the opening and closing tags to [} and {], instead of the [!, !], how will the |\w+='(?![!)[^']*'| section change. I tried a few things but wasn't capturing it.Gambia
It will be (?!\[\}) instead of (?!\[!). Also make sure you are escaping the { and } in the other places.Bazemore

© 2022 - 2024 — McMap. All rights reserved.