使用通配符匹配嵌套父组
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 会很清楚这一点,所有示例都是相对于上面显示的数据。
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)
)
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
和结尾 )
;只是其中的内容。但无论哪种方式都很好 - 哪个更容易。
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)
)
xxx
= eq
,所以正则表达式会寻找 <whitespace>(eq<whitespace>....)<whitespace>
同样,我将始终(通过 c#,而不是正则表达式)深入嵌套,例如,在第二个 if
中的以下 or
块不是整个字符串.所以我们可以只看第2个if
的or
内的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...)
.
既然已经给出了示例,那么以下是可以作为绝对原则的原则:
- 在所有情况下都会有 paren-groupings,我需要正则表达式 not 尝试匹配匹配内部的嵌套 paren-groupings,但只是外部匹配。但是内部分组应该 returned 作为外部匹配的一部分。任何内部嵌套的括号都应该被正则表达式视为普通字符串,并简单地 returned 匹配,而不是试图将它们视为匹配。总之,当正则表达式找到时,例如
(if
...它需要找到那个 (if
的结束 )
,并忽略里面的任何括号。
- 我需要能够以编程方式将我自己的通配符提供到正则表达式中,它可以是
if
、and
、or
等。通配符文本永远不会是特殊字符,只是普通的小写字母,并且在所有情况下都将以左括号开头,它本身将以白色 space 开头,然后将始终有一个右括号。在这些匹配的外括号之间,通常会有更多的括号,为了匹配目的应该忽略它们,但是return作为匹配的内容作为普通字符串编辑。
- 内部和外部匹配的括号总是正确的。开括号永远不会比闭括号多,反之亦然,这当然会混淆正则表达式。
- 一个正则表达式应该(我相信)能够容纳所有内容,我将在运行时提供通配符文本。
目前我的应用程序中有一个正则表达式,它几乎可以满足我在这里的要求,除了它匹配双引号集而不是 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
我需要解析一堆遗留的基于文件的数据,如下所示:
(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 会很清楚这一点,所有示例都是相对于上面显示的数据。
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)
)
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
和结尾 )
;只是其中的内容。但无论哪种方式都很好 - 哪个更容易。
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)
)
xxx
=eq
,所以正则表达式会寻找<whitespace>(eq<whitespace>....)<whitespace>
同样,我将始终(通过 c#,而不是正则表达式)深入嵌套,例如,在第二个 if
中的以下 or
块不是整个字符串.所以我们可以只看第2个if
的or
内的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...)
.
既然已经给出了示例,那么以下是可以作为绝对原则的原则:
- 在所有情况下都会有 paren-groupings,我需要正则表达式 not 尝试匹配匹配内部的嵌套 paren-groupings,但只是外部匹配。但是内部分组应该 returned 作为外部匹配的一部分。任何内部嵌套的括号都应该被正则表达式视为普通字符串,并简单地 returned 匹配,而不是试图将它们视为匹配。总之,当正则表达式找到时,例如
(if
...它需要找到那个(if
的结束)
,并忽略里面的任何括号。 - 我需要能够以编程方式将我自己的通配符提供到正则表达式中,它可以是
if
、and
、or
等。通配符文本永远不会是特殊字符,只是普通的小写字母,并且在所有情况下都将以左括号开头,它本身将以白色 space 开头,然后将始终有一个右括号。在这些匹配的外括号之间,通常会有更多的括号,为了匹配目的应该忽略它们,但是return作为匹配的内容作为普通字符串编辑。 - 内部和外部匹配的括号总是正确的。开括号永远不会比闭括号多,反之亦然,这当然会混淆正则表达式。
- 一个正则表达式应该(我相信)能够容纳所有内容,我将在运行时提供通配符文本。
目前我的应用程序中有一个正则表达式,它几乎可以满足我在这里的要求,除了它匹配双引号集而不是 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