使用通配符匹配嵌套父组

Matched nested paren-groups with wildcard

我需要解析一堆遗留的基于文件的数据,如下所示:

(or


        (if         (eq ?SSD-enart_Cl:sName rueck1)

                then

                (or (eq ?SSD_Cl:sName sb405)
                    (eq ?SSD_Cl:sName sb455)
                    (eq ?SSD_Cl:sName sb52)
                )
        )



        (if         (eq ?SSD-enart_Cl:sName rueck3)

                then

                (or (eq ?SSD_Cl:sName sb38)
                    (eq ?SSD_Cl:sName sb405)
                    (eq ?SSD_Cl:sName sb43)
                    (eq ?SSD_Cl:sName sb455)
                    (eq ?SSD_Cl:sName sb48)
                )
        )



        (if     
                    (eq ?SSD-enart_Cl:sName r-SSD-ck4)
            

                then

                    (<> ?SSD_Cl:qty -1)
        )


)

我需要一个匹配的通配符正则表达式和 return 组以 <whitespace>(xxx<whitespace>....)<whitespace> 开头的分组括号,其中 xxx 是通配符字符串,而 <whitespace> 不是文字字符串,但可以是任何白色 space,最常见的是制表符、space 或换行符。而且我需要在比赛中忽略嵌套的双亲组,但作为其外部比赛的一部分包括在内。一些 scenarios/examples 会很清楚这一点,所有示例都是相对于上面显示的数据。

  1. xxx = or,所以正则表达式会查找 <whitespace>(or<whitespace>....)<whitespace>

这应该return单匹配:(or ... )里面数据的全部内容,具体来说:

        (if         (eq ?SSD-enart_Cl:sName rueck1)

                then

                (or (eq ?SSD_Cl:sName sb405)
                    (eq ?SSD_Cl:sName sb455)
                    (eq ?SSD_Cl:sName sb52)
                )
        )



        (if         (eq ?SSD-enart_Cl:sName rueck3)

                then

                (or (eq ?SSD_Cl:sName sb38)
                    (eq ?SSD_Cl:sName sb405)
                    (eq ?SSD_Cl:sName sb43)
                    (eq ?SSD_Cl:sName sb455)
                    (eq ?SSD_Cl:sName sb48)
                )
        )



        (if     
                    (eq ?SSD-enart_Cl:sName r-SSD-ck4)
            

                then

                    (<> ?SSD_Cl:qty -1)
        )
  1. xxx = if,所以正则表达式会查找 <whitespace>(if<whitespace>....)<whitespace>

这应该 return 正好匹配 3 个:

第 1 场比赛:

(if         (eq ?SSD-enart_Cl:sName rueck1)
        then

        (or (eq ?SSD_Cl:sName sb405)
            (eq ?SSD_Cl:sName sb455)
            (eq ?SSD_Cl:sName sb52)
        )
)

第 2 场比赛:

(if         (eq ?SSD-enart_Cl:sName rueck3)

            then

            (or (eq ?SSD_Cl:sName sb38)
                (eq ?SSD_Cl:sName sb405)
                (eq ?SSD_Cl:sName sb43)
                (eq ?SSD_Cl:sName sb455)
                (eq ?SSD_Cl:sName sb48)
            )
)

第 3 场比赛:

(if     
            (eq ?SSD-enart_Cl:sName r-SSD-ck4)
            

            then

            (<> ?SSD_Cl:qty -1)
)

注意:我并不严格需要在匹配中返回的字符串中包含 (if 和结尾 );只是其中的内容。但无论哪种方式都很好 - 哪个更容易。

  1. xxx = or,所以正则表达式会查找 <whitespace>(or<whitespace>....)<whitespace>

对于这个例子,我们只需要查看 or 之一,因为我将始终评估给定 if 的字符串,而不是整个字符串。所以我们可以只看第2个if中的or,例如:

(if         (eq ?SSD-enart_Cl:sName rueck3)

            then

            (or (eq ?SSD_Cl:sName sb38)
                (eq ?SSD_Cl:sName sb405)
                (eq ?SSD_Cl:sName sb43)
                (eq ?SSD_Cl:sName sb455)
                (eq ?SSD_Cl:sName sb48)
            )
)

这应该 return 完全匹配 1 个:

(or (eq ?SSD_Cl:sName sb38)
        (eq ?SSD_Cl:sName sb405)
        (eq ?SSD_Cl:sName sb43)
        (eq ?SSD_Cl:sName sb455)
        (eq ?SSD_Cl:sName sb48)
)
  1. xxx = eq,所以正则表达式会寻找 <whitespace>(eq<whitespace>....)<whitespace>

同样,我将始终(通过 c#,而不是正则表达式)深入嵌套,例如,在第二个 if 中的以下 or 块不是整个字符串.所以我们可以只看第2个ifor内的eq,例如:

(or (eq ?SSD_Cl:sName sb38)
    (eq ?SSD_Cl:sName sb405)
    (eq ?SSD_Cl:sName sb43)
    (eq ?SSD_Cl:sName sb455)
    (eq ?SSD_Cl:sName sb48)
)

而且我正好期待 5 场比赛,每场都在 (eq...).

既然已经给出了示例,那么以下是可以作为绝对原则的原则:

目前我的应用程序中有一个正则表达式,它几乎可以满足我在这里的要求,除了它匹配双引号集而不是 opening/closing parens:

public static MatchCollection GetQuotedStrings(string str) {
       Regex regex = new Regex("(\"([^\"]|\"\")*\")"); 
       return regex.Matches(str);
}

上面的函数出色地找到了双引号的“尾端集”,即使在匹配字符串中经常有更多的双引号。我需要的是类似的:opening/closing 分组的括号集,但总是在开头的括号旁边有一个通配符字符串。不幸的是,我是一个正则表达式初学者,无法弄清楚如何以有效的方式修改上述正则表达式。

编辑

我担心我上面超级详细的文章会吓跑人们。这比看起来要简单得多,所以让我简化一下。我需要一个匹配 (if...) 的所有实例的正则表达式,其中 (if 将始终以白色 space 开头,并且始终会有结束符 ),并且 ...代表杂项很多

唯一棘手的部分是在外部 (if...) 分组中经常会有其他 (..) 分组,并且这些内部分组需要像普通字符串一样处理,而不是与正则表达式匹配。就是这样。

这就是答案:

$@"\({wildcard}(?>\((?<c>)|[^()]+|\)(?<-c>))*(?(c)(?!))\)"

我在运行时将 wildcard 传递给函数,它运行良好。

我从这里收集了解决方案:

Regular expression to match balanced parentheses