【问题标题】:Regular Expression not working when same condition is nested嵌套相同条件时,正则表达式不起作用
【发布时间】:2019-01-24 03:18:08
【问题描述】:

背景:我只是在摆弄一个仅提供 if/for/render 的简单模板的想法,以了解它的可行性以及在我的个人项目中使用是否有意义。与使用 NVelocity 或 Razor 或其他任何东西相反。

我写了一个正则表达式:

(?:(?:(?<open>\[if (?<if>[a-zA-Z0-9\.]+)\])(?<content>[^\[]*))+(?:[^\[]*(?<close-open>\[end if\]))+)+(?(open)(?!))

当与示例文本一起使用时:

<div>
[if variable3]{{variable3}}[end if]
</div>

<div>
[if variable1]

    {{variable1}}

    [if variable2]
        <br>
        {{variable2}}
    [end if]

[end if]
</div>

它按预期工作。我得到 2 个匹配项,如果第 2 个匹配项有效,我可以解析内部捕获。

问题是如果我有多个嵌套匹配。所以给定:

<div>
[if variable3]{{variable3}}[end if]
</div>

<div>
[if variable1]

    {{variable1}}

    [if variable2]
        <br>
        {{variable2}}
    [end if]

    [if variable4]
        <br>
        {{variable4}}
    [end if]

    [if variable5]
        <br>
        {{variable5}}
    [end if]

[end if]
</div>

我最终得到的是第一个捕获是正确的,然后是所有 3 个单独的捕获,而不是第二个匹配的外部捕获。

如果我扩展捕获以忽略内部内容的 \[,它会导致第一个和第二个匹配组合成一个匹配。 :(

有谁知道如何解决这个问题? (如果您对如何执行此模板有更好的了解,会很想知道 cmets)

【问题讨论】:

  • 我建议查看 XML 解析器。尝试使用正则表达式解析 HTML 是 generally discouraged
  • @LewsTherin 但他没有解析 HTML?
  • @LewsTherin 我没有解析 HTML,我正在解析我自己的语法。
  • 如何从 HTML 文档中提取数据不被视为解析?您需要能够区分您感兴趣的数据和 HTML 标记。我对解析的理解错了吗?
  • 您可以正确匹配所有块与(?s)\[if\s+(?&lt;if&gt;[^][]+)](?&gt;(?:(?!\[if\s|\[end\ if]).)+|(?&lt;close-open&gt;)\[end\ if]|(?&lt;open&gt;)\[if\s+(?&lt;if&gt;[^][]+)])*(?(open)(?!))\[end\ if],但我对捕获内容有疑问。

标签: c# regex


【解决方案1】:

你可以使用

@"(?s)\[if\s+(?<if>[^][]+)](?<fullBody>(?>(?:(?!\[if\s|\[end\ if]).)+|(?<-open>)\[end\ if]|(?<open>)\[if\s+(?<if>[^][]+)])*(?(open)(?!)))\[end\ if]"

请参阅regex demo

详情(请注意,由于 x 修饰符,您可能会在 C# 代码中使用它):

@"(?sx)               # Singleline and IgnorePatternWhitespace flags on
  \[if\s+             # "[if" and then 1+ whitespaces
    (?<if>[^][]+)     # "If" group: one or more chars other than "]"
  ]                   # a "]" char
   (?<fullBody>       # Group "fullBody" containing all nested if blocks
     (?>              # Start of an atomic group
       (?:(?!\[if\s|\[end\ if]).)+|    # any char, 1+ occurrences, that does not start the "[if " or "[end if]" substring, or...
       (?<-open>)\[end\ if]|           # "[end if]" substring and an item is popped from Group "open", or
       (?<open>)\[if\s+(?<if>[^][]+)]  # Group "open": "[if", 1+ whitespaces, Group "if": 1+ chars other than "[" and "]", and then a "]" char
     )*               # repeat atomic group patterns 0 or more times
     (?(open)(?!))    # A conditional: if Group "open" has any items on its stack, fail and backtrack
   )                  # End of fullBody group
  \[end\ if]"         # "[end if]" substring

如果您不关心 if 块是否嵌套在哪个块中,您可以使用此正则表达式的变体清楚地获得 if 块的完整列表:

var pattern = @"(?s)(?=(?<ifBlock>\[if\s+(?<if>[^][]+)](?<fullBody>(?>(?:(?!\[if\s|\[end\ if]).)+|(?<-open>)\[end\ if]|(?<open>)\[if\s+(?<if>[^][]+)])*(?(open)(?!)))\[end\ if]))";

上面的模式只是被另一个命名的捕获组包裹,并被放置在一个正向前瞻中。虽然匹配值始终为空,但组将保存您可能需要的所有值。

【讨论】:

  • 您先生,是字面上的正则表达式之神。我真的很感激你甚至添加了详细的分解来解释这一切。非常有帮助,值得学习。
猜你喜欢
  • 1970-01-01
  • 2017-07-01
  • 2019-06-25
  • 2016-08-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多