使用正则表达式在C#中递归获取内部模式。

7
我知道在.NET中有关于正则表达式递归的几个问题。我可以编写相当复杂的正则表达式,但这种递归超出了我的能力,我无法编写它。
以下是最接近我想要的问题。 first question, second question
但它匹配整个字符串,我希望匹配结果在一个集合中,最好是从最内部的匹配开始或按某种顺序。同时,它只匹配一个开头字符和一个结束字符。我的开头和结束字符是两个字符,[!和!]。
我的输入字符串将是这样的。
[!a='test' b='[!a='innertest' b='innervalue'!]'!]

我需要先找到最内层的部分,[!a='innertest' b='innervalue'!],然后通过我的表达式树对其进行评估,再对包含它的父级进行评估。有人能帮忙吗?
1个回答

13

这是一个可能能够满足你需求的模式:

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

它将按顺序为每个项返回最内层的项。为了解释我的意思,考虑以下代码:

[!a='test' c='[!x='blah'!]' b='[!a='[!y='innermost'!]' b='innervalue'!]' !]
它将会在"inner"组的捕获集合中返回以下匹配结果:
x='blag'
y='innermost'
a='[!y='innermost'!]' b='innervalue'

因此,对于[! .. !]中的每个x=y项,它将按内向外的顺序给出匹配项。

如果您还希望捕获整个表达式,则可以像这样修改:

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

给定:

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

并且,为了解释正则表达式:

^       # 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

这看起来不错。谢谢你的帮助。我要试一下。有没有办法告诉顺序,比如最里面的先,因为我需要先评估它。 - Alex J
不是直接的。你可以通过使用每个捕获的Capture.StartCapture.Length属性来解决它,因为这将让你知道哪些捕获包含哪些其他捕获。然而,如果每个x='...'只能依赖于它所包含的内容,那么这个顺序应该可以正常工作。 - porges
这非常接近我想要的。感谢您的努力。你一定是个天才!最后一个问题。如果我想将开放和关闭标签更改为[}和{],而不是[!,!],那么|\w+='(?![!)[^']*'|部分会如何更改。我尝试了一些东西,但没有捕获它。 - Alex J
т«Ѓт░єТў» (?!\[\}) УђїСИЇТў» (?!\[!)сђѓТГцтцќ№╝їУ»иуА«С┐ЮтюетЁХС╗ќСйЇуй«УйгС╣Ѕ { тњї }сђѓ - porges

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接